Selection Modifiers
 
 
 

Selection modifiers alter the selection level of objects. An example is the Volume Select modifier which can be found at \MAXSDK\SAMPLES\MODIFIERS\SELMOD.CPP.

Below is the implementations of Modifer::InputType(), Modifer::ChannelsUsed(), and Modifer::ChannelsChanged().

Class_ID InputType() {
  returntriObjectClassID;
}
 
ChannelMask ChannelsUsed() {
  returnOBJ_CHANNELS;
} 
 
ChannelMask ChannelsChanged() {
   returnSELECT_CHANNEL|SUBSEL_TYPE_CHANNEL|GEOM_CHANNEL;
}

Note that Modifier::ChannelsChanged() for the Volume Select modifier doesn't specify DISP_ATTRIB_CHANNEL. Technically it really should since it changes the mesh display flags. The reason this isn't a problem however is that this is only a single integer in the Mesh and isn't dynamically allocated. So it is actually always present even without actually being specified in channels used or channels used.

Below is the implementation of the Volume Select modifier's Modifer::ModifyObject(). Note that when the modifier is done it updates the validity of the object flowing down the pipeline by calling UpdateValidity() on the four appropriate channels.

void SelMod::ModifyObject(TimeValue t, ModContext &mc,
            ObjectState *os, INode *node)
{
   Interval valid = LocalValidity(t);
   intlevel, method, type, vol, invert;
 
   pblock->GetValue(PB_LEVEL,t,level,FOREVER);
   pblock->GetValue(PB_METHOD,t,method,FOREVER);
   pblock->GetValue(PB_TYPE,t,type,FOREVER);
   pblock->GetValue(PB_VOLUME,t,vol,FOREVER);
   pblock->GetValue(PB_INVERT,t,invert,FOREVER);
 
   assert(os->obj->IsSubClassOf(triObjectClassID));
   TriObject *obj = (TriObject*)os->obj;
   Mesh &mesh = obj->mesh;
 
   // Prepare the controller and set up mats
   if (!tmControl || (flags&CONTROL_OP)) InitControl(mc,obj,type,t);
   Matrix3 tm;
   tm = Inverse(CompMatrix(t,&mc,NULL,TRUE,FALSE));
 
   Box3 mcbox = *mc.box;
   FixupBox(mcbox);
 
   switch (level)
   {
     case SEL_OBJECT:
      obj->mesh.selLevel = MESH_OBJECT;
      obj->mesh.ClearDispFlag(DISP_VERTTICKS|DISP_SELVERTS|DISP_SELFACES);
      break;
 
     case SEL_VERTEX:
      obj->mesh.selLevel = MESH_VERTEX;
      obj->mesh.SetDispFlag(DISP_VERTTICKS|DISP_SELVERTS);
      SelectVertices(obj->mesh,method,type,vol,invert,tm,mcbox);
      break;
 
     case SEL_FACE:
      obj->mesh.selLevel = MESH_FACE;
      obj->mesh.SetDispFlag(DISP_SELFACES);
      SelectFaces(obj->mesh,method,type,vol,invert,tm,mcbox);
      break;
   }
 
   obj->UpdateValidity(SELECT_CHAN_NUM,valid);
   obj->UpdateValidity(GEOM_CHAN_NUM,valid);
   obj->UpdateValidity(TOPO_CHAN_NUM,valid);
   obj->UpdateValidity(SUBSEL_TYPE_CHAN_NUM,FOREVER);
}