Search Tips

Search is based on keyword.

`Ex: "Procedures"`

Do not search with natural language

`Ex: "How do I write a new procedure?"`

Give Feedback Support Portal

# Q100326: Writing and testing custom Ops

Warning: This article contains links to external websites

#### SUMMARY

Ops are the building blocks of operations that create and manipulate 3D scene data in Katana. Ops are instances of plug-ins called Op Types written in C++. They can perform various operations, manipulating the scene graph and modifying attributes, using Katana’s Op API.

This article provides a step by step example of writing, compiling and testing a custom Op based on the HelloWorld example Op found under $KATANA_ROOT/plugins/Src/Ops.

#### MORE INFORMATION

Before creating a custom Op, it may be helpful to take a look at the example Ops located in $KATANA_ROOT/plugins/Src/Ops. This tutorial is based specifically on the HelloWorld example Op.

The following steps describe how to modify the source code of this Op to create an Op that can read and set attributes at locations in the scene graph.

1. Modify the `cook()` function in $KATANA_ROOT/plugins/Src/Ops/HelloWorld/src/HelloWorldOp.cpp to read as follows:

    static void cook(Foundry::Katana::GeolibCookInterface& interface)
    {
       FnAttribute::StringAttribute typeAttr = interface.getAttr("type");
       interface.setAttr("testType",  typeAttr);

        if (interface.atRoot())
        {
           interface.setAttr("hello", FnAttribute::StringAttribute("world!"));
        }
    }

2. To build the example Op plugins, please follow the instructions given in $KATANA_ROOT/plugins/Src/README.md.
   Make sure the source file path is pointing to the correct Katana version in the cmake command. It is not necessary to include -DCMAKE_PREFIX_PATH in the cmake command, as this is specifying dependencies for other Op examples that we are not interested in in this case.

3. Once the plug-ins have been built and installed, make sure the install directory is part of KATANA_RESOURCES. Using the command as it is given in README.md, the MyKatanaResources directory should be included in KATANA_RESOURCES.

4. Launch Katana, create a CameraCreate node and connect to it a GenericOp node.

5. Set the opType parameter of the GenericOp node to "HelloWorld". The result of this should be that an attribute named testType is set on each location and the value of the attribute will be the location's type. Additionally, an attribute named "hello" will be set on /root, to a value of "world!"

The `cook()` function could also be modified to read or set any attribute that you are interested in at a location, or perform a number of other operations.

For more functions that can be used in custom Ops, please see the Katana Developer Guide on the Cook Interface (C++).

NOTE: The Op runs at all locations by default (as specified by the applyWhere parameter in the GenericOp node), so it will automatically traverse the entire scene graph. In the example above, this results in the testType attribute being set at all locations.

Because this is not always desirable, the example above also includes an if statement checking whether interface is `atRoot()` - this will result in the statements inside the if block to only be executed when the Op is running at the topmost location it has been cooked at, and you can use `interface.stopChildTraversal()` after the if statement to stop the Op from traversing the entire scene graph beneath that topmost location.

If you would like to create a custom node type to use your Op, please refer to the example of a NodeTypeBuilder-based node type found under $KATANA_ROOT/plugins/Src/Ops/Messer/RegisterMesserNode.py.

Some NodeTypeBuilder API functions are documented in the Katana Developer Guide.

If you are encountering any issues with these steps, then please open a Support ticket and let us know the issue you are encountering and the troubleshooting steps you have taken so far.

For more information on how to open a Support ticket, please refer to Q100064: How to raise a support ticket.