#include <stdlib.h>
#include <UT/UT_DSOVersion.h>
#include <UT/UT_NTStreamUtil.h>
#include <PRM/PRM_Include.h>
#include <OP/OP_OperatorTable.h>
#include <OP/OP_Input.h>
#include <VOP/VOP_Operator.h>
#include "VOP_Switch.h"
using namespace HDK_Sample;
void
newVopOperator(OP_OperatorTable *table)
{
OP_Operator *op;
op = new VOP_Operator("hdkswitch",
"HDK Switch",
VOP_Switch::myConstructor,
VOP_Switch::myTemplateList,
0,
VOP_VARIABLE_INOUT_MAX,
"*",
0,
OP_FLAG_UNORDERED,
1);
table->addOperator(op);
}
static const char *theInputRoot = "input";
static const char *theOutputName = "result";
static PRM_Name theSwitcherName("switcher", "Switcher Index");
static PRM_Name theOutOfBoundsName("outofbounds",
"Out Of Bounds Behavior");
static PRM_Name theOutOfBoundsChoices[] =
{
PRM_Name("last", "Output Last Input Value"),
PRM_Name("zero", "Output Zero"),
PRM_Name()
};
enum
{
VOP_SWITCH_OOB_LAST,
VOP_SWITCH_OOB_ZERO
};
static PRM_ChoiceList theOutOfBoundsMenu(PRM_CHOICELIST_SINGLE,
theOutOfBoundsChoices);
OP_Node *
VOP_Switch::myConstructor(OP_Network *net, const char *name, OP_Operator *entry)
{
return new VOP_Switch(net, name, entry);
}
PRM_Template VOP_Switch::myTemplateList[] =
{
PRM_Template(PRM_INT, 1, &theSwitcherName, PRMzeroDefaults),
PRM_Template(PRM_ORD, 1, &theOutOfBoundsName, PRMzeroDefaults,
&theOutOfBoundsMenu),
PRM_Template()
};
VOP_Switch::VOP_Switch(OP_Network *parent, const char *name, OP_Operator *entry)
: VOP_Node(parent, name, entry)
{
}
VOP_Switch::~VOP_Switch()
{
}
unsigned
VOP_Switch::disableParms()
{
int changed = 0;
changed += enableParm(theSwitcherName.getToken(), getInput(0) == 0);
return changed;
}
void
VOP_Switch::getCode(UT_String &codestr, VOP_CodeVarMapperContext *context)
{
if (getNumVisibleInputs() > 2)
{
UT_OStrStream os;
UT_String inputName, outputName;
int outofbounds = OUTOFBOUNDS();
int i, j, next, first = 1;
getOutputName(outputName, 0);
for( i = getConnectedInputIndex(0), j = 0; i >= 0; i = next, j++ )
{
next = getConnectedInputIndex(i);
getInputName(inputName, i);
if( next >= 0 || outofbounds == VOP_SWITCH_OOB_ZERO )
{
if( !first )
os << "else ";
os << "if( $" << theSwitcherName.getToken();
os << " == " << j << " )" << endl;
os << " ";
}
else if( !first )
{
os << "else" << endl << " ";
}
os << "$" << outputName << " = $" << inputName << ";" << endl;
first = 0;
}
if( outofbounds == VOP_SWITCH_OOB_ZERO )
{
VOP_Type outputType = getOutputType(0);
if( !first )
os << "else" << endl << " ";
os << "$" << outputName << " = ";
os << myLanguage->getEmptyConstantString(outputType) << ";" << endl;
}
os << ends;
codestr.harden(os.str());
os.rdbuf()->freeze(0);
}
}
const char *
VOP_Switch::inputLabel(unsigned idx) const
{
if (idx >= orderedInputs())
{
static UT_String theLabel;
char numstr[UT_NUMBUF];
theLabel = "Input Number ";
UT_String::itoa(numstr, idx + 1 - orderedInputs());
theLabel += numstr;
return theLabel;
}
else
return theSwitcherName.getLabel();
}
const char *
VOP_Switch::outputLabel(unsigned idx) const
{
UT_ASSERT(idx == 0);
return "Chosen Value";
}
void
VOP_Switch::getInputNameSubclass(UT_String &in, int idx) const
{
if (idx >= orderedInputs())
{
char numstr[UT_NUMBUF];
in = theInputRoot;
UT_String::itoa(numstr, idx + 1 - orderedInputs());
in += numstr;
}
else
in = theSwitcherName.getToken();
}
int
VOP_Switch::getInputFromNameSubclass(const UT_String &in) const
{
int inputnum = -1;
if( in == theSwitcherName.getToken() )
return 0;
if( !strncmp(in, theInputRoot, strlen(theInputRoot)) )
inputnum = ::atoi((const char *)in + strlen(theInputRoot));
return inputnum - 1 + orderedInputs();
}
VOP_Type
VOP_Switch::getInputTypeSubclass(int idx)
{
VOP_Node *vop;
OP_Input *input;
VOP_Type vextype = VOP_TYPE_UNDEF;
if( idx >= orderedInputs() )
{
if( input = getInputReference(orderedInputs(), 0) )
{
vop = CAST_VOPNODE(input->getNode());
if( vop )
vextype = vop->getOutputType(input->getNodeOutputIndex());
}
}
else
vextype = myLanguage->conditionType(VOP_TYPE_INTEGER);
return vextype;
}
void
VOP_Switch::getAllowedInputTypesSubclass(unsigned idx, VOP_VopTypeArray &voptypes)
{
VOP_Node *vop;
OP_Input *input;
if( idx >= orderedInputs() )
{
if( input = getInputReference(orderedInputs(), 0) )
{
vop = CAST_VOPNODE(input->getNode());
if( vop )
voptypes.append(vop->getOutputType(input->getNodeOutputIndex()));
}
}
else
voptypes.append(myLanguage->conditionType(VOP_TYPE_INTEGER));
}
void
VOP_Switch::getOutputNameSubclass(UT_String &name, int idx) const
{
UT_ASSERT(idx == 0);
name = theOutputName;
}
VOP_Type
VOP_Switch::getOutputTypeSubclass(int idx)
{
UT_ASSERT(idx == 0);
return getInputType(orderedInputs());
}
unsigned
VOP_Switch::getNumVisibleInputs() const
{
int max = nInputs();
if( max < orderedInputs() )
max = orderedInputs();
return max + 1;
}
unsigned
VOP_Switch::orderedInputs() const
{
return 1;
}
int
VOP_Switch::OUTOFBOUNDS()
{
return evalInt(theOutOfBoundsName.getToken(), 0, 0.0f);
}