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. |
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. |
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