Writing SubComponent Filters

To filter selections of subcomponents (edges, points, or polygons), Softimage prefers the Subset callback to the Match callback. That is, Softimage calls Subset instead of the Match callback when a user selects some subcomponents. You should always provide a Subset callback for a subcomponent filter.

Subset

When Softimage calls Subset, it puts an XSICollection in the Input attribute of the callback context. This collection contains one CollectionItem for each 3D object with selected subcomponents. In the callback function, you get the selected subcomponents from the CollectionItem.SubComponent.ComponentCollection property.

The following example shows the typical structure of a Subset callback for subcomponent filter. First, the callback creates a new XSICollection, which will be used to hold the output of the callback. Then for each 3D object, Subset finds the matching polygons and creates a new SubComponent object with them. The new SubComponent objects are added to the output collection, and the collection is put in the Output attribute of the callback context.

function MyPolygonFilter_Subset( oContext )
{
   var oFilter = oContext.Source;
   logmessage( oFilter.Name + "_Subset");

   // Create a new XSICollection to hold the output
   var cloSubset = new ActiveXObject( "XSI.Collection" );

   // Get the XSI.Collection from the context
   // The collection contains one CollectionItem for each object with selected polygons
   var cloObjects = oContext.GetAttribute( "Input" );

   for (var objEnumerator = new Enumerator(cloObjects) ; !objEnumerator.atEnd(); objEnumerator.moveNext())
   {
       // Get the CollectionItem
       var oItem = objEnumerator.item();

       // Get the SubComponent object
       var oPolySubComponent = oItem.SubComponent;

       if ( !( (classname(oPolySubComponent) == "SubComponent") && ( oPolySubComponent.type == "polySubComponent" ) ) )
          continue;

       // This array will hold the indices of the polygons that match the filter conditions
       var aIndices = new Array();

       // Enumerate the selected polygons; if a polygon matches, put its index in the array
       for (var polyEnumerator = new Enumerator(oPolySubComponent.ComponentCollection) ; !polyEnumerator.atEnd(); polyEnumerator.moveNext())
       {
          var oPoly = polyEnumerator.item();
          if ( polygon_isamatch( oPoly ) )
          {
              aIndices.push( oPoly.index );
          }
       }

       // Create a SubComponent from the subset of polygons that match, and add the SubComponent to the output
       if ( aIndices.length > 0 )
       {
          var oSubComponent = oPolySubComponent.Parent3DObject.ActivePrimitive.Geometry.CreateSubComponent(siPolygonCluster, aIndices );
          cloSubset.Add( oSubComponent );
       }
   }

   // You always set the Output attribute, even if the subset is empty
   oContext.SetAttribute( "Output", cloSubset );

   // Return True if the subset is non-empty
   return (cloSubset.Count > 0);
}


// Select only polygons with more than 3 points
function polygon_isamatch( oPoly )
{
   return ( oPoly.NbPoints != 3 )
}

Another way to implement a Subset callback is to work directly with the SubComponent objects passed in by Softimage. In this approach, you use SubComponent.RemoveElement to remove the polygons that don't match, and put the modified SubComponent in the output collection.

function MyPolygonFilter_Subset( oContext )
{
   var cloSubset = new ActiveXObject( "XSI.Collection" );

   var cloObjects = oContext.GetAttribute( "Input" );

   for (var objEnumerator = new Enumerator(cloObjects) ; !objEnumerator.atEnd(); objEnumerator.moveNext())
   {
       var oItem = objEnumerator.item();

       var oPolySubComponent = oItem.SubComponent;

       if ( !( (classname(oPolySubComponent) == "SubComponent") && ( oPolySubComponent.type == "polySubComponent" ) ) )
          continue;

       // Get a copy of the PolygonFaceCollection; 
       // We'll enumerate cloTmpCopy, and modify oPolySubComponent.ComponentCollection 
       var cloTmpCopy = oPolySubComponent.ComponentCollection;

       // Enumerate the selected polygons; if a polygon doesn't match, remove it from oPolySubComponent
       for (var polyEnumerator = new Enumerator(cloTmpCopy) ; !polyEnumerator.atEnd(); polyEnumerator.moveNext())
       {
          var oPoly = polyEnumerator.item();
          if ( !polygon_isamatch( oPoly ) )
          {
              oPolySubComponent.RemoveElement( oPoly.index );
          }
       }

       // Add the modified SubComponent the output collection
       if ( aIndices.length > 0 )
       {
          cloSubset.Add( oPolySubComponent );
       }
   }

   oContext.SetAttribute( "Output", cloSubset );

   return (cloSubset.Count > 0);
}

Match

For subcomponent filters, Subset is the most important callback. Softimage won't call Match unless a filter doesn't have a Subset callback. However, Match is required, so you must provide an implementation. Typically, Match returns false as soon as it finds a subcomponent that doesn't match the filter conditions.

When Softimage calls Match for a subcomponent filter, it puts a SubComponent object in the callback context. The following example shows a typical structure for a Match callback.

function MyPolygonFilter_Match( oContext )
{
   // Get the SubComponent object from the context
   var oPolySubComponent = oContext.GetAttribute( "Input" );

   // Return false if we don't have a SubComponent, or we don't have polygons
   if ( !( (classname(oPolySubComponent) == "SubComponent") && ( oPolySubComponent.type == "polySubComponent" ) ) )
   {
       return false;
   }

   // Enumerate the selected polygons; Return false as soon as we find a polygon that doesn't match
   for (var polyEnumerator = new Enumerator(oPolySubComponent.ComponentCollection) ; !polyEnumerator.atEnd(); polyEnumerator.moveNext())
   {
       var oPoly = polyEnumerator.item();
       if ( !polygon_isamatch( oPoly ) )
       {
          return false;
       }
   }

   // If we make it here, all the polygons match
   return true;
}


Autodesk Softimage 2011