atomImportExport/atomCachedPlugs.cpp

atomImportExport/atomCachedPlugs.cpp
//
// File Name: atomCachedPlugs.cpp
//
//
// When exporting we need to collect all items that we want to cache
// This holds cached only.
#include "atomCachedPlugs.h"
#include <maya/MAnimUtil.h>
#include <maya/MPlugArray.h>
#include <maya/MObjectArray.h>
template <class T>
void atomCachedValues<T>::resize(unsigned int numItems,unsigned int stride)
{
mNumItems = numItems;
mStride = stride;
int total = numItems *stride;
mValues.resize(total);
}
template <class T>
void atomCachedValues<T>::setValue(T &value,unsigned int item,unsigned int element)
{
mValues[(item * mStride) + element] = value;
}
template <class T>
T atomCachedValues<T>::getValue(unsigned int item, unsigned int element)
{
return mValues[(item * mStride) + element];
}
/*
atomShortValues
*/
atomShortValues::atomShortValues(MPlug &plug, unsigned int numItems) :atomBasePlugAndValues(plug)
{
mCachedValues.resize(numItems,1);
}
void atomShortValues::setValue(MDGContext &context,unsigned int index)
{
MObject attribute = mPlug.attribute();
if ( attribute.hasFn( MFn::kNumericAttribute ) )
{
MFnNumericAttribute fnAttrib(attribute);
switch(fnAttrib.unitType())
{
{
bool value;
mPlug.getValue(value,context);
short ival = value == true ? 1 : 0;
mCachedValues.setValue(ival,index);
break;
}
{
char value;
mPlug.getValue(value,context);
short ival = (short) value;
mCachedValues.setValue(ival,index);
break;
}
{
short value;
mPlug.getValue(value,context);
mCachedValues.setValue(value,index);
break;
}
default:
break;
}
}
else if( attribute.hasFn( MFn::kEnumAttribute ) )
{
short value;
mPlug.getValue(value,context);
mCachedValues.setValue(value,index);
}
}
void atomShortValues::writeToAtomFile(ofstream & clip)
{
for(unsigned int i=0;i<mCachedValues.numItems();++i)
{
clip << mCachedValues.getValue(i);
clip << " ";
}
}
/*
atomIntValues
*/
atomIntValues::atomIntValues(MPlug &plug, unsigned int numItems) :atomBasePlugAndValues(plug)
{
mCachedValues.resize(numItems,1);
}
void atomIntValues::setValue(MDGContext &context,unsigned int index)
{
MObject attribute = mPlug.attribute();
if ( attribute.hasFn( MFn::kNumericAttribute ) )
{
MFnNumericAttribute fnAttrib(attribute);
if(fnAttrib.unitType()==MFnNumericData::kLong)
{
int value;
mPlug.getValue(value,context);
mCachedValues.setValue(value,index);
}
}
}
void atomIntValues::writeToAtomFile(ofstream & clip)
{
for(unsigned int i=0;i<mCachedValues.numItems();++i)
{
clip << mCachedValues.getValue(i);
clip << " ";
}
}
/*
atomFloatValues
*/
atomFloatValues::atomFloatValues(MPlug &plug, unsigned int numItems,unsigned int stride) :atomBasePlugAndValues(plug)
{
mCachedValues.resize(numItems,stride);
}
void atomFloatValues::setValue(MDGContext &context,unsigned int index)
{
MObject attribute = mPlug.attribute();
if ( attribute.hasFn( MFn::kNumericAttribute ) )
{
MFnNumericAttribute fnAttrib(attribute);
switch(fnAttrib.unitType())
{
{
float value;
mPlug.getValue(value,context);
mCachedValues.setValue(value,index);
break;
}
default:
break;
}
}
}
void atomFloatValues::writeToAtomFile(ofstream & clip)
{
for(unsigned int i=0;i<mCachedValues.numItems();++i)
{
for(unsigned int j=0;j<mCachedValues.stride();++j)
{
clip << mCachedValues.getValue(i,j);
clip << " ";
}
}
}
/*
atomDoubleValues
*/
atomDoubleValues::atomDoubleValues(MPlug &plug, unsigned int numItems,double scale) :atomBasePlugAndValues(plug), mScale(scale)
{
mCachedValues.resize(numItems,1);
}
void atomDoubleValues::setValue(MDGContext &context,unsigned int index)
{
MObject attribute = mPlug.attribute();
if ( attribute.hasFn( MFn::kNumericAttribute ) )
{
MFnNumericAttribute fnAttrib(attribute);
switch(fnAttrib.unitType())
{
{
double value;
mPlug.getValue(value,context);
mCachedValues.setValue(value,index);
break;
}
default:
break;
}
}
else if( attribute.hasFn( MFn::kUnitAttribute ) )
{
MFnUnitAttribute fnAttrib(attribute);
switch(fnAttrib.unitType())
{
{
double value;
mPlug.getValue(value,context);
value *= mScale;
mCachedValues.setValue(value,index);
break;
}
{
double value;
mPlug.getValue(value,context);
value *= mScale;
mCachedValues.setValue(value,index);
break;
}
{
double value;
mPlug.getValue(value,context);
mCachedValues.setValue(value,index);
break;
}
default:
{
break;
}
}
}
}
void atomDoubleValues::writeToAtomFile(ofstream & clip)
{
for(unsigned int i=0;i<mCachedValues.numItems();++i)
{
clip << mCachedValues.getValue(i);
clip << " ";
}
}
/*
atom cached plugs
*/
atomCachedPlugs::atomCachedPlugs(MString &nodeName,MObject &object, const MPlugArray& animatablePlugs,
bool sdk, bool constraint, bool animLayers, std::set<std::string> &attrStrings,
atomTemplateReader &templateReader,unsigned int numItems,MAngle::Unit angularUnit,
MDistance::Unit linearUnit)
{
getCachedPlugs(nodeName,animatablePlugs, sdk, constraint, animLayers, attrStrings,templateReader,numItems,angularUnit,linearUnit);
}
atomCachedPlugs::~atomCachedPlugs()
{
for(unsigned int z =0; z< mCachedPlugs.size(); ++z)
{
if(mCachedPlugs[z])
delete mCachedPlugs[z];
}
}
void atomCachedPlugs::getCachedPlugs(MString &nodeName, const MPlugArray &animatablePlugs,
bool sdk, bool constraint, bool animLayers,
std::set<std::string> &attrStrings,atomTemplateReader &templateReader,unsigned int numItems,
MAngle::Unit angularUnit,
MDistance::Unit linearUnit)
{
std::set<std::string>::const_iterator constIter = attrStrings.end();
unsigned int numPlugs = animatablePlugs.length();
MPlugArray cachedPlugs;
for (unsigned int i = 0; i < numPlugs; i++)
{
MPlug plug = animatablePlugs[i];
MPlugArray destPlugArray;
//temp test here. If the plug is connected, but not directly to an anim curve, then cache it
//will get smarter about this later, but good for testing for now.
bool isConnected = plug.connectedTo (destPlugArray, true,false);
bool isConnectedButNotToAnimCurve = (isConnected && (destPlugArray.length() == 1 &&
destPlugArray[0].node().hasFn(MFn::kAnimCurve)==false));
bool animCurveIsConnected = false;
//now check to see if the anim curve returned is connected and driven by something else
if (isConnectedButNotToAnimCurve ==false && destPlugArray.length() ==1 &&
destPlugArray[0].node().hasFn(MFn::kAnimCurve)==true)
{
MPlug curve = destPlugArray[0];
destPlugArray.clear();
curve.connectedTo(destPlugArray,true,false);
animCurveIsConnected = destPlugArray.length() > 0; //
}
bool shouldBeCached = isConnectedButNotToAnimCurve ||animCurveIsConnected;
//if not cached yet, see if hooked up to a sdk, don't do the same for a constraint or anim layers
//since shouldBeCached will be true for them. Only sdk's may still be false here.
if(sdk==false) //sdk is false when not doing export edits so do caching instead.
{
MObjectArray animationNodes;
MPlugArray drivers;
if(MAnimUtil::findSetDrivenKeyAnimation(plug,animationNodes,
drivers)) //it's an sdk
shouldBeCached = true;
}
if (shouldBeCached )
{
MPlug attrPlug (plug);
MObject attrObj = attrPlug.attribute();
MFnAttribute fnLeafAttr (attrObj);
MString attrName;
atomBase::getAttrName(plug,attrName);
//template filter check first
if(templateReader.findNodeAndAttr(nodeName,attrName) == false)
continue;
//then if we have specified attr strings then don't save it out if it's not found
//must use shortName since the channelBox command will always return a short name
//the long name flag there is only used to turn long name (or nice name) display on
if(attrStrings.size() == 0 || attrStrings.find(std::string(fnLeafAttr.shortName().asChar())) != constIter)
{
//okay at this point we may have a contraint which we don't want to cache if we are export editing them
if(constraint)
{
MObject constraint;
MObjectArray targets;
if(MAnimUtil::findConstraint(plug,constraint,targets)) //it's a constraint, don't cache
continue;
}
//or it may be hooked up to animLayers, again we don't want to cache it if that option is on
if(animLayers)
{
MObjectArray layers;
MPlugArray plugs;
if(MAnimUtil::findAnimationLayers(plug,layers,plugs))
continue;
}
cachedPlugs.append(plug);
}
}
}
//okay if we have any cached plugs then create the correct value array
if(cachedPlugs.length() >0 )
{
mCachedPlugs.resize(cachedPlugs.length());
for(unsigned int i =0 ;i< cachedPlugs.length(); ++i)
{
atomBasePlugAndValues * plugAndValue = NULL;
MPlug &plug = cachedPlugs[i];
MObject attribute = plug.attribute();
if ( attribute.hasFn( MFn::kNumericAttribute ) )
{
MFnNumericAttribute fnAttrib(attribute);
switch(fnAttrib.unitType())
{
{
plugAndValue = new atomShortValues(plug, numItems);
break;
}
{
plugAndValue = new atomIntValues(plug, numItems);
break;
}
{
plugAndValue = new atomFloatValues(plug, numItems,1);
break;
}
{
plugAndValue = new atomDoubleValues(plug, numItems,1.0);
break;
}
default:
break;
}
}
else if( attribute.hasFn( MFn::kUnitAttribute ) )
{
MFnUnitAttribute fnAttrib(attribute);
switch(fnAttrib.unitType())
{
{
MAngle angle(1.0);
double scale = angle.as(angularUnit);
plugAndValue = new atomDoubleValues(plug, numItems,scale);
break;
}
{
MDistance distance(1.0);
double scale = distance.as(linearUnit);
plugAndValue = new atomDoubleValues(plug, numItems,scale);
break;
}
{
plugAndValue = new atomDoubleValues(plug, numItems,1.0);
break;
}
default:
{
break;
}
}
}
else if( attribute.hasFn( MFn::kEnumAttribute ) )
{
plugAndValue = new atomShortValues(plug, numItems);
}
mCachedPlugs[i] = plugAndValue;
}
}
}
MPlug& atomCachedPlugs::getPlug(unsigned int item)
{
return mCachedPlugs[item]->getPlug();
}
void atomCachedPlugs::calculateValue(MDGContext &ctx,unsigned int item)
{
for(unsigned int i = 0;i< mCachedPlugs.size(); ++i)
{
if(mCachedPlugs[i])
mCachedPlugs[i]->setValue(ctx,item);
}
}
void atomCachedPlugs::writeValues(ofstream &clip,unsigned int item)
{
if(item< mCachedPlugs.size())
{
if(mCachedPlugs[item])
mCachedPlugs[item]->writeToAtomFile(clip);
}
}
//todo need to add layerName support
bool atomCachedPlugs::isAttrCached(const MString &attrName,const MString &layerName)
{
if(hasCached())
{
//currently since the plugs are in a vector we iterate one by one,
//we may change this implementation to use a map instead to speed this up though it won't be too
//bad we don't think.
for(unsigned int i = 0;i< mCachedPlugs.size(); ++i)
{
if(mCachedPlugs[i])
{
MPlug plug = mCachedPlugs[i]->getPlug();
MString name;
atomBase::getAttrName(plug,name);
if(name == attrName)
return true;
}
}
}
return false;
}