赞
踩
写这个东西的缘由是一个同事给我说了一个他以前碰到的一个问题:一个文件里有上万条动画曲线,要删除某一帧前面的帧,也要删掉某一帧后面的帧,相当于是掐头去尾,但从功能上来说这个mel完全可以胜任,但是执行起来效率就特别的低,于是他找另一个同事帮他写了个command,这样就将一个6G的含有上万条动画曲线的文件,只用了40多分钟就删完了,最后只剩下1G,而用mel删了一个小时还不到10%,可见二者效率相差。于是自己也想试着写一些,真正写起来没啥难点,主要是两个类,MFnAnimCurve和MAnimCurveChange,同时也实现了redo和undo,实现这个主要是用一个指针在堆中创建一个内存空间,然后将removekey都缓存到这块内存空间里,最后用它自身方法就可以实现redo和undo,自己测试,我这个command效率上没有他的那个夸张,应该是有些地方还不够优化,后面再继续完善吧。想想自己和他们的距离,不,那是天堑,自己还得多加努力啊。具体代码如下:
- #include<maya/MPxCommand.h>
- #include <maya/MFnPlugin.h>
- #include <maya/MSyntax.h>
- #include <maya/MDistance.h>
- #include <maya/MItDependencyNodes.h>
- #include <maya/MDGModifier.h>
- #include <maya/MArgDatabase.h>
- #include <maya/MFnAnimCurve.h>
- #include <maya/MAnimCurveChange.h>
-
- class DeleteKeysCmd : public MPxCommand
- {
- public:
- DeleteKeysCmd();
- ~DeleteKeysCmd();
- virtual MStatus doIt( const MArgList& );
- virtual MStatus redoIt();
- virtual MStatus undoIt();
- virtual bool isUndoable() const { return true; };
- static void *creator(){ return new DeleteKeysCmd; }
- static MSyntax newSyntax();
-
- private:
- MTime startFrame;
- MTime endFrame;
- MAnimCurveChange* pAnimCache;
-
- };
-
- const char *startFrameFlag = "-sf", *startFrameLongFlag = "-startFrame";
- const char *newendFrameFlag = "-ef", *newendFrameLongFlag = "-endFrame";
-
- DeleteKeysCmd::DeleteKeysCmd()
- {
- startFrame.setValue( 0 );
- endFrame.setValue( 100 );
- }
-
- DeleteKeysCmd::~DeleteKeysCmd()
- {
- delete pAnimCache;
- }
-
- MSyntax DeleteKeysCmd::newSyntax()
- {
- MSyntax syntax;
- syntax.addFlag( startFrameFlag, startFrameLongFlag, MSyntax::kLong );
- syntax.addFlag( newendFrameFlag, newendFrameLongFlag, MSyntax::kLong );
-
- return syntax;
- }
-
- MStatus DeleteKeysCmd::doIt( const MArgList &args )
- {
- MStatus stat;
- pAnimCache = NULL;
- pAnimCache = new MAnimCurveChange();
-
- MArgDatabase argData( syntax(), args, &stat );
- if( !stat )
- return stat;
- if( argData.isFlagSet( startFrameFlag ) )
- argData.getFlagArgument( startFrameFlag, 0, startFrame);
- if( argData.isFlagSet( newendFrameLongFlag ) )
- argData.getFlagArgument( newendFrameLongFlag, 0, endFrame);
-
- MDGModifier modifier;
- MItDependencyNodes animCurves(MFn::kAnimCurve);
-
- for (; !animCurves.isDone(); animCurves.next())
- {
- MObject currentItem = animCurves.item();
- if ( currentItem.isNull() )
- {
- continue;
- }
- MFnAnimCurve fnCurve (currentItem);
- unsigned int numKeys = fnCurve.numKeys();
- if (numKeys == 0)
- {
- modifier.deleteNode(currentItem);
- }
- else
- {
- unsigned int startFrameIndex = fnCurve.findClosest(startFrame);
- for(unsigned int i = 0; i < startFrameIndex; i++)
- {
- fnCurve.remove(0, pAnimCache);
- }
- unsigned int endFrameIndex = fnCurve.findClosest(endFrame);
- unsigned int numKeysToRemoves = numKeys -1 - endFrameIndex;
- for(unsigned int i = 0; i < numKeysToRemoves; i++)
- {
- fnCurve.remove(endFrameIndex + 1, pAnimCache);
- }
- }
- }
- return stat;
- }
-
- MStatus DeleteKeysCmd::undoIt()
- {
- if( pAnimCache != NULL )
- pAnimCache -> undoIt();
- return MS::kSuccess;
- }
-
- MStatus DeleteKeysCmd::redoIt()
- {
- if( pAnimCache != NULL )
- pAnimCache -> redoIt();
- return MS::kSuccess;
- }
-
- MStatus initializePlugin( MObject obj )
- {
- MFnPlugin plugin( obj, "Lulongfei", "1.0" );
- MStatus stat;
- stat = plugin.registerCommand( "deleteKeys", DeleteKeysCmd::creator, DeleteKeysCmd::newSyntax );
- if ( !stat )
- stat.perror( "registerCommand failed" );
- return stat;
- }
-
- MStatus uninitializePlugin( MObject obj )
- {
- MFnPlugin plugin( obj );
- MStatus stat;
- stat = plugin.deregisterCommand( "deleteKeys" );
- if ( !stat )
- stat.perror( "deregisterCommand failed" );
- return stat;
- }
- def removeInvalidKeys(start, end):
- animCurves = om.MItDependencyNodes(om.MFn.kAnimCurve)
- while not animCurves.isDone():
- modifier = om.MDGModifier()
- fnCurveCache = oma.MAnimCurveChange()
- currentItem = animCurves.item()
- fnCurve = oma.MFnAnimCurve(currentItem)
-
- if fnCurve.numKeys():
- # remove all frame before the start keyframe
- startFrameIndex = fnCurve.findClosest(om.MTime(start))
- for i in xrange(startFrameIndex):
- fnCurve.remove(0, fnCurveCache)
-
- # remove all frame after the end keyframe
- endFrameIndex = fnCurve.findClosest(om.MTime(end))
- for i in xrange(endFrameIndex, fnCurve.numKeys() - 1):
- fnCurve.remove(endFrameIndex + 1, fnCurveCache)
- #fnCurveCache.undoIt()
-
- else:
- modifier.deleteNode(currentItem)
-
- animCurves.next()
而python则直接可以调用function了,removeInvalidKeys(20, 90)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。