Registering a Custom ICENode

ICENodes must be defined first before they can be applied in Softimage. The registration process must happen in the XSILoadPlugin callback when the ICENode self-installable plug-in is loaded. ICENodes are defined with the ICENodeDef class and registered with PluginRegistrar::RegisterICENode.

 

You can get your Custom ICENode to appear in the Preset Manager with a special icon (thumbnail). See Customizing Icons for Custom ICENodes for more information.

ICENodeDef Objects

ICENodes are configured with an ICENodeDef object which provides the API with definitions for the input and output ports (ICENodeDef::AddInputPort, ICENodeDef::AddOutputPort), groups (ICENodeDef::AddPortGroup) and to specify the threading model (ICENodeDef::PutThreadingModel, ICENodeDef::GetThreadingModel).

Each custom ICENode has at least one output and zero or more input ports. Each port must be configured for the specific data it needs to read or write to. ICENodePorts need to be defined with a group, which can contain an unlimited number of ports. You usually want to regroup ports in the same logical group but nothing prevents you from defining one port per group. Input and output ports cannot be mixed in the same group.

Port Types

Input and output ports use a strong typing system defined with a 3-category type set:

Data type
Type of data the port can support. See siICENodePortDataType for a list of available data types.

Structure type
The way the data is stored when passed to the Evaluate callback. See siICENodePortStructureType for a list of available structure types.

Context type
Specifies the elements on which the data is evaluated. See siICENodeEvaluationContextType for a list of available context types.

The type of a port is specified with a triple value set, one for each category.For example:

// single array of vector3 elements evaluated for each mesh vertex
siICENodePortDataVector3 + siICENodePortStructureSingle + siICENodeEvaluationContextComponent0D:
// single array of booleans evaluated per object
siICENodePortDataBool + siICENodePortStructureSingle + siICENodeEvaluationContextSingleton:
// 2D array of long values evaluated per mesh polygons
siICENodePortDataLong + siICENodePortStructureArray + siICENodeEvaluationContextComponent2D:

Port Polymorphism

In general, port types of a same category can be combined together to allow port polymorphism. Polymorphism refers to a ICENode port’s ability to support multiple types. This is helpful if you need to define general-purpose nodes where the input data is used generically (see Polymorphism handling section for details.). You can assign multiple types to ports by using the bitwise OR operator with AddInputPort and AddOutputPort methods.

Port Constraint Maps

Constraint maps force multiple input and output ports to use the same data, structure or context types. For instance, mapping can be used to enforce the context of input port A and output port B to siICENodeEvaluationContextSingleton. In some scenarios, input ports can also be constrained between each other, as can output ports. You can set up a mapping by linking the port types or structures with an integer: use the same integer for ports that need to match or ULONG_MAX if no constraints are required. Port constraints are specified when defining ports with AddInputPort and AddOutputPort.

Unique Identifiers

Ports and groups must be defined with unique identifiers, ICENodeDef will issue an error if duplicate identifiers are used. A simple way to ensure unique identifiers is to use an enum. Unique ids also ensures full backward compatibility on ports in case ICENode ports or groups are removed or new ones added. Ports can be added or removed without affecting the loading of old scenes saved with a previous version of a specific ICENode.

 

You must not change the enum identifiers in order to maintain backward compatibility. Once an identifier is used, it must remain intact for the entire life of the ICENode and must not be reused by another port or group. You can only add new identifiers at the end of the enum when new ports are required.

Registration Example

This example demonstrates how to define and register an ICENode with 2 input ports and 2 output ports:

#include <xsi_application.h>
#include <xsi_mdnodecontext.h>
#include <xsi_mdnodedef.h>
#include <xsi_pluginregistrar.h>
#include <xsi_status.h>
#include <xsi_factory.h>
#include <xsi_math.h>
#include <xsi_vector3f.h> 
#include <xsi_indexset.h> 
#include <xsi_dataarray.h>

using namespace XSI; 
using namespace MATH; 

// user defined IDs
enum IDs
{
   // groups
   IdGr_In,
   IdGr_OutX,
   IdGr_OutY,

   // ports
   IdPort_InPos = 100,
   IdPort_OutX,
   IdPort_InValue,
   IdPort_OutY,

   // maps
   typemapid = 200,
   structmapid, 
   contextmapid,

   UndefinedID = ULONG_MAX
};

XSIPLUGINCALLBACK CStatus XSILoadPlugin( PluginRegistrar& in_reg )
{
   in_reg.PutAuthor(L"Softimage");
   in_reg.PutName(L"ICENode registration sample plugin");
   in_reg.PutVersion(1,0);

   Application app ;

   // Creates an ICENodeDef object from the factory
   Factory factory = app.GetFactory();
   ICENodeDef nodeOpDef = Application().GetFactory().CreateICENodeDef( in_name );

   // Set the threading model to multi-threading (default)
   CStatus st;
   st = nodeOpDef.PutThreadingModel( siICENodeMultiThreading );
   st.AssertSucceeded( ) ;

   // Create the input port
   st = nodeOpDef.AddPortGroup( IdGr_In );
   st.AssertSucceeded( ) ;

   // Create the input port of type Vector3f per vertex
   siICENodePortDataType nDataType = siICENodePortDataVector3;
   siICENodePortStructureType nStructType = siICENodePortStructureSingle;
   siICENodeEvaluationContextType nContextType = siICENodeEvaluationContextComponent0D;

   // constraint maps are not used for data and structure types, set them with the default ID
   IDs typemapValue = UndefinedID;
   IDs structmapValue = UndefinedID
   IDs contextmapValue = contextmapid;

   st = nodeOpDef.AddInputPort( 
                                       IdPort_InPos,  // input port index 
                                       IdGr_In,  // index of group to add port to
                                       nDataType,  // data type for port
                                       nStructType,  // structure type for port
                                       nContextType,  // context type for port
                                       L"vector",  // port name
                                       L"vector",  // port scripting name
                                       MATH::CVector3f(1.0, 1.0, 1.0),  // default value
                                       typemapValue,  // data type constraint
                                       structmapValue,  // structure type constraint
                                       contextmapValue  // context type constraint
   );
   st.AssertSucceeded( ) ;

   // Create the input port of type Long with a 'wildcard' context
   nDataType = siICENodePortDataLong;
   nStructType = siICENodePortStructureSingle;
   nContextType = siICENodeEvaluationContextAny;

   st = nodeOpDef.AddInputPort( 
                                       IdPort_InValue,  // input port index 
                                       IdGr_In,  // index of group to add port to
                                       nDataType,  // data type for port
                                       nStructType,  // structure type for port
                                       nContextType,  // context type for port
                                       L"InValue",  // port name
                                       L"InValue",  // port scripting name
                                       55L,  // default value
                                       typemapValue,  // data type constraint
                                       structmapValue,  // structure type constraint
                                       contextmapValue  // context type constraint
   );
   st.AssertSucceeded( ) ;

   // Create 2 float output ports
   nDataType = siICENodePortDataFloat;

   // Note: IdPort_InPos and IdPort_inValue are context constrained by the output ports, 
   // if one of the output port context is set to siICENodeEvaluationContextSingleton at 
   // connection time, these ports will also be set to siICENodeEvaluationContextSingleton 
   // (and vice-versa)

   st = nodeOpDef.AddPortGroup( IdGr_OutX );
   st.AssertSucceeded( ) ;

   st = nodeOpDef.AddOutputPort( 
                                       IdPort_OutX,  // output port index 
                                       IdGr_OutX,  // output port group index
                                       nDataType,  // data type for port
                                       nStructType,  // structure type for port
                                       nContextType,  // context type for port
                                       L"x",  // port name
                                       L"x",  // port scripting name
                                       typemapValue,  // data type constraint
                                       structmapValue,  // structure type constraint
                                       contextmapValue  // context type constraint
   );
   st.AssertSucceeded( ) ;

   st = nodeOpDef.AddPortGroup( IdGr_OutY );
   st.AssertSucceeded( ) ;

   st = nodeOpDef.AddOutputPort( 
                                       IdPort_OutY,  // output port index 
                                       IdGr_OutY,  // output port group index
                                       nDataType,  // data type for port
                                       nStructType,  // structure type for port
                                       nContextType,  // context type for port
                                       L"y",  // port name
                                       L"y",  // port scripting name
                                       typemapValue,  // data type constraint
                                       structmapValue,  // structure type constraint
                                       contextmapValue  // context type constraint
   );
   st.AssertSucceeded( ) ;

   // Register the new ICENode and add it to the Custom ICENode category
   PluginItem nodeItem = in_reg.RegisterICENode(nodeOpDef);
   nodeItem.PutCategories(L"Custom ICENode Sample");

   return CStatus::OK;
}


Autodesk Softimage v7.5