#include <math.h>
#include <maya/MIOStream.h>
#include <maya/MPxNode.h>
#include <maya/MFnNumericAttribute.h>
#include <maya/MFnTypedAttribute.h>
#include <maya/MFnStringData.h>
#include <maya/MFnPlugin.h>
class stringFormat : public MPxNode
{
public:
stringFormat();
virtual ~stringFormat();
virtual MStatus compute( const MPlug& plug, MDataBlock& data );
static void* creator();
static MStatus initialize();
public:
static MTypeId id;
static MObject attrFormat;
static MObject attrValues;
static MObject attrOutput;
};
MTypeId stringFormat::id( 0x81034 );
MObject stringFormat::attrFormat;
MObject stringFormat::attrValues;
MObject stringFormat::attrOutput;
void* stringFormat::creator()
{
return new stringFormat();
}
MStatus stringFormat::initialize()
{
MFnNumericAttribute numAttr;
MFnTypedAttribute typedAttr;
MFnStringData stringData;
MStatus stat;
MStatus stat2;
attrFormat = typedAttr.create("format", "f", MFnData::kString,
stringData.create(&stat2), &stat);
CHECK_MSTATUS( stat2 );
CHECK_MSTATUS( stat );
CHECK_MSTATUS( typedAttr.setStorable( true ) );
CHECK_MSTATUS( typedAttr.setKeyable( true ) );
attrValues = numAttr.create("values", "v", MFnNumericData::kDouble,
0, &stat);
CHECK_MSTATUS( stat );
CHECK_MSTATUS( numAttr.setArray( true ) );
CHECK_MSTATUS( numAttr.setReadable( false ) );
CHECK_MSTATUS( numAttr.setIndexMatters( true ) );
CHECK_MSTATUS( numAttr.setStorable( true ) );
CHECK_MSTATUS( numAttr.setKeyable( true ) );
attrOutput = typedAttr.create( "output", "o", MFnData::kString,
stringData.create(&stat2), &stat);
CHECK_MSTATUS( stat2 );
CHECK_MSTATUS( stat );
CHECK_MSTATUS( typedAttr.setWritable( false ) );
CHECK_MSTATUS( typedAttr.setStorable( false ) );
CHECK_MSTATUS( addAttribute( attrFormat ) );
CHECK_MSTATUS( addAttribute( attrValues ) );
CHECK_MSTATUS( addAttribute( attrOutput ) );
CHECK_MSTATUS( attributeAffects( attrFormat, attrOutput ) );
CHECK_MSTATUS( attributeAffects( attrValues, attrOutput ) );
return MS::kSuccess;
}
stringFormat::stringFormat() {}
stringFormat::~stringFormat() {}
int findNextMatch(MString & string, int indx, int & param, char & letter)
{
const char * str = string.asChar();
while (str[indx]) {
if ((str[indx] == '^') &&
(str[indx+1] >= '0') && (str[indx+1] <= '9') &&
(str[indx+2] >= 'a') && (str[indx+1] <= 'z')) {
param = str[indx+1] - '0';
letter = str[indx+2];
return indx+1;
}
indx++;
}
return -1;
}
MStatus stringFormat::compute (const MPlug& plug, MDataBlock& data)
{
MStatus status;
if (plug == attrOutput) {
MDataHandle inputData = data.inputValue (attrFormat, &status);
CHECK_MSTATUS( status );
MString format = inputData.asString();
MArrayDataHandle vals = data.outputArrayValue(attrValues, &status);
CHECK_MSTATUS( status );
int indx = 0;
int param;
char letter;
while ((indx = findNextMatch(format, indx, param, letter)) > 0) {
double val = 0.;
status = vals.jumpToElement(param);
if (status == MStatus::kSuccess) {
MDataHandle thisVal = vals.inputValue( &status );
if (status == MStatus::kSuccess) {
val = thisVal.asDouble();
}
}
MString replace;
bool valid = false;
switch (letter) {
case 'd':
val = floor(val+.5);
case 'f':
replace.set(val);
valid = true;
break;
case 't':
{
const char * sign = "";
if (val<0) {
sign = "-";
val = -val;
}
int valInt = (int)(val+.5);
int sec = valInt / 24;
int frame = valInt - sec * 24;
int min = sec / 60;
sec -= min * 60;
int hour = min / 60;
min -= hour * 60;
char buffer[90];
if (hour>0)
sprintf(buffer, "%s%d:%02d:%02d.%02d",
sign, hour, min, sec, frame);
else
sprintf(buffer, "%s%02d:%02d.%02d",
sign, min, sec, frame);
replace = buffer;
}
valid = true;
break;
}
if (valid) {
format = format.substring(0, indx-2) +
replace + format.substring(indx+2, format.length()-1);
indx += replace.length() - 3;
}
}
MDataHandle output = data.outputValue(attrOutput, &status );
CHECK_MSTATUS( status );
output.set( format );
} else {
return MS::kUnknownParameter;
}
return MS::kSuccess;
}
MStatus initializePlugin ( MObject obj )
{
MStatus status;
MFnPlugin plugin( obj, PLUGIN_COMPANY, "8.0", "Any");
CHECK_MSTATUS_AND_RETURN_IT(
plugin.registerNode( "stringFormat", stringFormat::id,
stringFormat::creator, stringFormat::initialize));
CHECK_MSTATUS(plugin.registerUI("stringFormatCreateUI",
"stringFormatDeleteUI", "", ""));
return status;
}
MStatus uninitializePlugin( MObject obj)
{
MStatus status;
MFnPlugin plugin( obj );
CHECK_MSTATUS_AND_RETURN_IT(plugin.deregisterNode( stringFormat::id ));
return status;
}