Given a node, parameters can be looked up either by name or by index. The recommended approach is to always look up parameters by name. The parameter name to index translation is fairly fast since it uses hash tables.
The value of a particular parameter can be obtained using the various parameter evaluation functions in OP_Parameters. To set the value on parameter component, use the various parameter setting functions.
In both cases, it is also necessary to supply the evaluation time. Often times, this information is already given to you as explicit function parameter, or indirectly via an OP_Context parameter. If given an OP_Context object, simply use OP_Context::getTime(). In absence of this, you can obtain the current evaluation time via the CHgetEvalTime() function.
When evaluating parameters, there are always two forms of each eval function: one explicitly supplying the "thread" id parameter, and another that simply uses UTgetSTID() as the thread id. If you have an OP_Context parameter, you can use the explicit thread id version of the eval function by passing it the return value of OP_Context::getThread().
void someFunction(OP_Node *node, OP_Context &context) { float now = context.getTime(); float tx; // evaluate the translate x parameter tx = node->evalFloat("t", /*component_index=*/ 0, now); // set the translate y parameter to 2.5, creating a keyframe if a channel // exists node->setFloat("t", /*component_index=*/1, now, 2.5, /*set_keyframe=*/true); // set the translate y parameter following channel references first, but do // not create a keyframe if the final parameter component contains a // channel node->setChRefFloat("t", /*component_index=*/1, now, 2.5); }
When new multi-parm child instance parameters are created, the pound (#) character is substituted with the instance index as the actual parameter name. Note that the starting index can be any arbitrary number but it is usually 0 or 1.
In OP_Parameters, there are Inst versions of the eval and set functions specifically geared for multi-parms (eg. OP_Parameters::evalFloatInst() and OP_Parameters::setFloatInst()). These functions take an array of instance indices (inst parameter), along with the length of the array (nestlevel parameter). The nestlevel parameter for these functions default to 1 so that for non-nested multi-parms, we can simply pass it the address of our single instance index.
Let's take an example from the BlendShapes SOP which has a multi-parm named "nblends" (label "Blends"). Its multi-parm instance has just one parameter named "weight#".
void someFunction(OP_Node *blend_sop, OP_Context &context) { float t = context.getTime(); int num_instances = blend_sop->evalInt("nblends", 0, t); int start_idx = blend_sop->getParm("nblends").getMultiStartOffset(); int instance_idx; // evaluate all multi-parm instances float * weights = new float[num_instances]; for (int i = 0; i < num_instances; i++) { instance_idx = start_idx + i; weights[i] = evalFloatInst("weight#", &instance_idx, 0, t); } // ... do something with weights ... delete [] weights; // add a new multi-parm instance with a 0.2 weight value blend_sop->setInt("nblends", 0, t, num_instances + 1); instance_idx = start_idx + num_instances; blend_sop->setIntInst(0.2, "weight#", &instance_idx, 0, t); }
To perform a lookup using a ramp parameter, OP_Parameters::updateRampFromMultiParm() provides a means of marshaling the data into a UT_Ramp object. If you modify a UT_Ramp object, you can transfer it back to the ramp parameter via OP_Parameters::updateMultiParmFromRamp().
void someFunction(OP_Node *node, OP_Context &context, float u) { float t = context.getTime(); UT_Ramp ramp; float values[4]; node->updateRampFromMultiParm(t, node->getParm("ramp_name"), ramp); ramp.rampLookup(u, values); // for float ramps, only values[0] will contain valid data // if you modify UT_Ramp, you can marshal it back to the ramp parameter... node->updateMultiParmFromRamp(t, ramp, node->getParm("ramp_name"), false); }
1.5.9