Default Attribute Producer Plug-ins

A number of aspects of the Katana ecosystem follow the principle of convention over configuration. For example, shaders may contain hundreds of configurable parameters but the shader author provides sensible default values for most of these parameters, this saves artists’ time by only requiring them to provide values in situations where the defaults aren’t suitable. Similarly, renderers provide a vast array of configuration options with sensible defaults, users are only required to override values in situations where the defaults are not appropriate for their use.

One of the main problems with the convention over configuration principle is that it often requires users to have an in-depth knowledge of the available parameters, their default values and acceptable inputs. Default Attribute Producers (DAPs) provide a solution to this by interrogating default values, their acceptable inputs and then returning a description of each parameter. This description is then used (primarily) in Katana’s user interface to allow users to introspect all configurable aspects of a shader, renderer or any other plug-in that extends Katana.

DAPs are implemented as C++ plug-ins and called from within Ops. They are able to query the incoming scene graph at the point they are invoked (but not modify it) and callers may request the DAP limit the values it should provide by specifying the attrRoot parameter. For example a DAP for producing shader defaults may receive attrRoot = "material", in which case it should only return default values under the material.XXX attribute hierarchy.

DAPs are themselves evaluated within the Runtime. For each call to their cook() function they must generate and return an FnAttribute::GroupAttribute value for the requested context. The context is defined as:

  • Op / scene graph location combination - Op and scene graph location the calling Op is currently being evaluated at.
  • Attribute path - an optional string which is used to scope the work of the DAP to a specific portion of the attribute hierarchy at the current location.

This translates to the following basic C++ signature of a DAP:

class MyDefaultAttributeProducer : public FnDefaultAttributeProducer::DefaultAttributeProducer
{
public:

    static FnAttribute::GroupAttribute cook(
                const FnGeolibOp::GeolibCookInterface & interface,
                const std::string & attrRoot,
                const std::string & inputLocationPath,
                int32_t inputIndex);
};
Where:
  • interface - the same interface passed to your Op’s cook() function, you are free to query the incoming scene graph but not make modifications to the outgoing scene graph.
  • attrRoot - allows the caller to scope the work of the DAP at a particular location to a sub-tree of the attribute hierarchy. For example, to only return values for the material attribute.
  • inputLocationPath - allows the caller to specify an scene graph location in the incoming scene where attribute queries should be directed.
  • inputIndex - allows the caller to specify a particular branch on the incoming Op tree where attribute queries should be directed.

DAP Calling Conventions

As discussed previously, DAPs are called within Ops. You can invoke them by calling FnGeolibCookInterfaceUtils::cookDaps() and passing in the necessary arguments (available to you in your Op’s cook context). You’ll get an FnAttribute::GroupAttribute back which you can either query or include in your Op’s cook() output. A number of conventions exist for certain attributes (such as UI hints); these are explained in more detail below. However, you are free to define any format when implementing your own DAPs and Ops.

The cookDaps() method signature is as follows:

static FnAttribute::GroupAttribute cookDaps(
        const GeolibCookInterface & interface,
        const std::string & attrRoot,
        const std::string & inputLocationPath=std::string(),
        int inputIndex=kFnKatGeolibDefaultInput,
        const FnAttribute::Attribute & cookOrderAttr=FnAttribute::Attribute());

By default, when cookDaps() is called, the built-in Katana DAPs - Material and GenericAssign - will be evaluated first and then the remaining DAPs will be evaluated in an arbitrary order. You can override this default behaviour by passing an FnAttribute::StringAttribute containing an ordered array of DAPs to run. Any DAPs not in the list will be evaluated after in an arbitrary order. e.g.:

std::vector<std::string> newCookOrder;
newCookOrder.push_back("MyDefaultAttributeProducer");
newCookOrder.push_back("Material");
newCookOrder.push_back("GenericAssign");
FnAttribute::StringAttribute newCookOrder(newCookOrder, 1);

GroupAttibute defaultGroupAttr =
    FnGeolibCookInterfaceUtils::cookDaps(
        interface,"", "", kFnKatGeolibDefaultInput, newCookOrder);

When are DAPs called?

DAPs can be called at anytime during an Op’s cook call (even at render time). Some Ops (like the AttributePanelPolish Op), are only appended to the Op tree during a UI session and make explicit calls to retrieve default attribute values. This allows the Attributes tab to fill in the blanks when you view attributes.

Note

At present a number of Katana’s built-in DAPs are not threadsafe. Care should be taken to invoke cookDaps() only in serial sections of code.

DAPs will be evaluated by the following built-in Katana Ops:

  • AdjustScreenWindowResolve
  • AttributePanelPolish
  • LocalizeAttribute
  • ZoomToRect

DAP Attribute Conventions

Like Ops, DAPs impose no restrictions on attribute hierarchy (except that a GroupAttribute is returned) so any conventions largely depend on the consumer of the DAP’s return value.

If you’re writing a DAP for a particular purpose, such as to drive a custom UI tab, feel free to structure your GroupAttribute in a way most suited to your needs.

UI Hints Convention

If you’d like to integrate with areas in the Katana UI that display attribute values (such as the Attributes tab) you can include UI hints in the FnAttribute::GroupAttribute returned by your DAP’s cook() function, as the sample code below demonstrates:

FnDapUtil::SetAttrHints(gb, "attributeName",
        FnAttribute::GroupBuilder()
                        .set("help",
                                FnAttribute::StringAttribute("Some help text"))
                        .set("widget",
                                FnAttribute::StringAttribute("widgetName"))
                        .set("options",
                                FnAttribute::StringAttribute("widgetOptions"))
                        .build());
namespace Foundry
namespace Katana
class DefaultAttributeProducer
#include <FnDefaultAttributeProducerPlugin.h>

DefaultAttributeProducer and classes derived from it are never instantiated. The base class contains some common static functions used by the plugin system (setHost()/getHost()/flush()/createSuite()).

Each derived class should create a static cook function which will be registered in a FnDefaultAttributeProducerSuite_v1 instance.

The signature of the cook function implemented by DefaultAttributeProducer plugins is:

 static FnAttribute::GroupAttribute cook(
         const FnGeolibOp::GeolibCookInterface & interface,
         const std::string & attrRoot,
         const std::string & inputLocationPath,
         int32_t inputIndex);

namespace Foundry
namespace Katana
class FnGeolibCookInterfaceUtils
#include <FnGeolibCookInterfaceUtilsService.h>

Provides a number of utility functions commonly used by Ops.

Public Static Functions

static void matchesCEL(MatchesCELInfo &matchesCELInfo, const Foundry::Katana::GeolibCookInterface &interface, const FnAttribute::StringAttribute &cel, const std::string &inputLocationPath = std::string(), int inputIndex = kFnKatGeolibDefaultInput)

Evaluates the CEL expression against the input location path and updates matchesCELInfo based on the results.

Parameters
  • matchesCELInfo -

    a instance of MatchesCELInfo

  • interface -

    the GeolibCookInterface passed to your cook()() function.

  • cel -

    a StringAttribute instance containing the CEL expression to be evaluated

  • inputLocationPath -

    the input location path the CEL expression will be evaluated against.

  • inputIndex -

    the input index on the incoming scene to be queried (if for example attributes are reference in the CEL expression)

static FnAttribute::GroupAttribute cookDaps(const Foundry::Katana::GeolibCookInterface &interface, const std::string &attrRoot, const std::string &inputLocationPath = std::string(), int inputIndex = kFnKatGeolibDefaultInput, const FnAttribute::Attribute &cookOrderAttr = FnAttribute::Attribute ())

Invoke the Default Attribute Producers (DAPs) and return the result.

Return
an FnAttribute::GroupAttribute instance containing the result of evaluating the DAPs.
See
DefaultAttributeProducer
Parameters
  • interface -

    the GeolibCookInterface passed to your cook()() function.

  • attrRoot -

    the attribute from which DAPs will be invoked from, e.g. materials, will only invoke the DAPs for attributes beneath materials.

  • inputLocationPath -

    the input location path

  • inputIndex -

    the input index to query the incoming scene

  • cookOrderAttr -

    an optional FnAttribute::StringAttribute describing the order in which DAPs should be evaluated.

static BuildLocalsAndGlobalsInfo buildLocalsAndGlobals(const Foundry::Katana::GeolibCookInterface &interface, const std::string &attrRoot)
static FnAttribute::Attribute getDefaultDapCookOrder()
static FnAttribute::GroupAttribute resolveFileNamesWithinGroup(const Foundry::Katana::GeolibCookInterface &interface, const FnAttribute::GroupAttribute &inputGroup, const FnAttribute::StringAttribute &celAttr, int frameNumber)
static FnAttribute::StringAttribute resolveFileNameInString(const Foundry::Katana::GeolibCookInterface &interface, const FnAttribute::StringAttribute &inputString, int frameNumber)
static FnAttribute::Attribute getGlobalAttrGeneric(BaseGlobalAttributeProvider &provider, FnPlatform::StringView name, FnPlatform::StringView locationPath, bool *didAbortPtr = NULL)
static FNKAT_DEPRECATED FnAttribute::Attribute Foundry::Katana::FnGeolibCookInterfaceUtils::getGlobalAttrGeneric(BaseGlobalAttributeProviderLegacy & provider, const std::string & name, const std::string & locationPath, bool * didAbortPtr = NULL)

Private Functions

FnGeolibCookInterfaceUtils()

Private Static Functions

static const FnGeolibCookInterfaceUtilsHostSuite_v2 *_getSuite()
struct BuildLocalsAndGlobalsInfo

Public Members

FnAttribute::GroupAttribute locals
FnAttribute::GroupAttribute globals
struct MatchesCELInfo

Public Members

bool matches
bool canMatchChildren
class BaseGlobalAttributeProvider
#include <FnGeolibCookInterfaceUtilsService.h>

Base abstract class representing a generic interface to query global attributes starting from a specified scene graph location.

A global attribute provider walks towards the root location, its getAttr() implementation returning the attribute corresponding to attrPath on each invocation.

Public Functions

virtual ~BaseGlobalAttributeProvider()
virtual FnGeolibGlobalAttributeProviderStatus getAttr(FnPlatform::StringView attrPath, FnAttribute::Attribute *attributeOut) = 0
class BaseGlobalAttributeProviderLegacy

Public Functions

virtual ~BaseGlobalAttributeProviderLegacy()
virtual FNKAT_DEPRECATED FnGeolibGlobalAttributeProviderStatus Foundry::Katana::BaseGlobalAttributeProviderLegacy::provideAttribute(const std::string & attrPath, const std::string & leafLocationPath, int32_t relativeDepth, FnAttribute::Attribute * attributeOut) = 0