Channel Modifier (metaclass)

From The Foundry MODO SDK wiki
Jump to: navigation, search

The channel modifier SDK has been completely overhauled for MODO 10. Old channel modifiers will still function exactly as before and can continue to be compiled with the updated SDK, but new modifiers should use the improved SDK. This metaclass supports creating C++ channel modifiers.

Sample

This example is a C++ channel modifier that takes one input float and outputs twice that value. The client's code is a sub-class of CLxChannelModifier which declares the channels for the modifier in init_chan() (derived from CLxChannels) and performs the computation in eval() (derived from CLxChannelModManager). The wrapper code binds the channels to the Value objects in the class which can be read and written during evaluation.

class COperator :
		public CLxChannelModifier
{
    public:
	CLxUser_Value		 v_input, v_output;
 
		void
	init_chan (
		CLxAttributeDesc	&desc)
	{
		COperator		*op = 0;
 
		desc.add ("input", LXsTYPE_FLOAT);
		desc.chanmod_chan (LXfCHMOD_INPUT, &op->v_input);
 
		desc.add ("output", LXsTYPE_FLOAT);
		desc.chanmod_chan (LXfCHMOD_OUTPUT, &op->v_output);
	}
 
		void
	eval ()
	{
		double		 val;
 
		v_input.GetFlt (&val);
		v_output.SetFlt (val * 2.0);
	}
};
 
static CLxMetaRoot_ChannelModifier<COperator>	 meta ("cmDoubler");
 
	void
initialize ()
{
	meta.initialize ();
}

Some things to note. In defining channels we use the chanmod_chan() method. That associates value objects with channels for binding. The metaclass is actually a composite, consisting of a Channels metaclass and a ChannelModManager metaclass assembled into a subtree. We also use the CLxMetaRoot_ChannelModifier template rather than CLxMeta_ChannelModifier. This just saves us a step and creates all the relevant metaclasses under a root which can just be initialized directly without needing to be added.

Other Bindings

In addition to Value objects, input channels can also be bound to ValueArray objects, allowing multi-link channels to be read individually.

 	CLxUser_ValueArray	 v_multi;
 	[...]
 		desc.add ("multi", LXsTYPE_FLOAT);
 		desc.chanmod_chan (LXfCHMOD_INPUT | LXfCHMOD_MULTILINK, &op->v_multi);
 	[...]
 		v_multi.Count (&n);
 		for (i = 0; i < n; i++) {
 			v_multi.GetFloat(i, &val);
 			sum += val;
 		}

Channels can also be bound to Matrix objects, and writing to a Matrix output now automatically propagates to all outputs so only a single result needs to be generated.

 	CLxUser_Matrix	 v_matrix;
 	[...]
 		desc.add ("outMat", LXsTYPE_MATRIX4);
 		desc.chanmod_chan (LXfCHMOD_OUTPUT, &op->v_matrix);
 	[...]
 		v_matrix.Set4 (resultMatrix);

Channel modifiers can also read from time. There's no channel needed for this, just a float to get the result.

 	CLxUser_Value	 v_time;
 	[...]
 		desc.chanmod_time (&op->v_time);
 	[...]
 		double t;
 		v_time.GetFlt (&t);