diff options
| author | Ben Marsh <[email protected]> | 2019-10-22 09:07:59 -0400 |
|---|---|---|
| committer | Ben Marsh <[email protected]> | 2019-10-22 09:07:59 -0400 |
| commit | bd0027e737c6512397f841c22786274ed74b927f (patch) | |
| tree | f7ffbdb8f3741bb7f24635616cc189cba5cb865c /mayaPlug/shaveStyleCmd.cpp | |
| download | shave-and-a-haircut-bd0027e737c6512397f841c22786274ed74b927f.tar.xz shave-and-a-haircut-bd0027e737c6512397f841c22786274ed74b927f.zip | |
Adding Shave-and-a-Haircut 9.6
Diffstat (limited to 'mayaPlug/shaveStyleCmd.cpp')
| -rw-r--r-- | mayaPlug/shaveStyleCmd.cpp | 441 |
1 files changed, 441 insertions, 0 deletions
diff --git a/mayaPlug/shaveStyleCmd.cpp b/mayaPlug/shaveStyleCmd.cpp new file mode 100644 index 0000000..19f212a --- /dev/null +++ b/mayaPlug/shaveStyleCmd.cpp @@ -0,0 +1,441 @@ +// Shave and a Haircut +// (c) 2019 Epic Games +// US Patent 6720962 + +//Qt headers must be included before any others !!! +#include <QtCore/QEvent> +#include <QtCore/QElapsedTimer> +#include <QtGui/QMouseEvent> +#include <QtGui/QTabletEvent> + +#if QT_VERSION < 0x050000 +# include <QtGui/QApplication> +# include <QtGui/QWidget> +#else +# include <QtWidgets/QApplication> +# include <QtWidgets/QWidget> +#endif + +#include <maya/MArgDatabase.h> +#include <maya/MArgList.h> +#include <maya/MDagPath.h> +#include <maya/MFnDagNode.h> +#include <maya/MFnDoubleIndexedComponent.h> +#include <maya/MFnSingleIndexedComponent.h> +#include <maya/MGlobal.h> +#include <maya/MPxCommand.h> +#include <maya/MSelectionList.h> +#include <maya/MSyntax.h> +#include <maya/MString.h> + +#include "shaveGlobals.h" +#include "shaveHairShape.h" +#include "shaveSDK.h" +#include "shaveStyleCmd.h" +#include "shaveUtil.h" +#include "shaveCursorCtx.h" + +#include <vector> +#include <sstream> +#include <assert.h> +#include <time.h> +#include <string.h> +#include <stdlib.h> + +static const char* flAttenuate = "-attenuate"; +static const char* fsAttenuate = "-at"; +static const char* flGrowSelection = "-growSelection"; +static const char* fsGrowSelection = "-gs"; +static const char* flHideSelection = "-hideSelection"; +static const char* fsHideSelection = "-hs"; +static const char* flInvertSelection = "-invertSelection"; +static const char* fsInvertSelection = "-is"; +static const char* flLock = "-lock"; +static const char* fsLock = "-l"; +static const char* flMergeSelection = "-mergeSelection"; +static const char* fsMergeSelection = "-ms"; +static const char* flPopSelected = "-popSelected"; +static const char* fsPopSelected = "-ps"; +static const char* flPopZeroSized = "-popZeroSized"; +static const char* fsPopZeroSized = "-pzs"; +static const char* flRecomb = "-recomb"; +static const char* fsRecomb = "-r"; +static const char* flReplaceRest = "-replaceRest"; +static const char* fsReplaceRest = "-rr"; +static const char* flRotateSelectionUp = "-rotateSelectionUp"; +static const char* fsRotateSelectionUp = "-rsu"; +static const char* flSplitSelection = "-splitSelection"; +static const char* fsSplitSelection = "-ss"; +static const char* flToggleCollision = "-tglCollision"; +static const char* fsToggleCollision = "-tc"; +static const char* flUndo = "-undo"; +static const char* fsUndo = "-u"; +#ifdef GLOBAL_FALLBACK +static const char* flRedrawOnIdle = "-redrawOnIdle"; +static const char* fsRedrawOnIdle = "-rdi"; +static const char* flFullRedrawOnIdle = "-fullRedrawOnIdle"; +static const char* fsFullRedrawOnIdle = "-fri"; +#endif + +const MString shaveStyleCmd::commandName("shaveStyle"); + + +shaveStyleCmd::shaveStyleCmd() {} +shaveStyleCmd::~shaveStyleCmd() {} + + +void* shaveStyleCmd::createCmd() +{ + return new shaveStyleCmd(); +} + + +MSyntax shaveStyleCmd::createSyntax() +{ + MSyntax syntax; + + syntax.enableEdit(false); + syntax.enableQuery(false); + + syntax.addFlag(fsAttenuate, flAttenuate); + syntax.addFlag(fsGrowSelection, flGrowSelection); + syntax.addFlag(fsHideSelection, flHideSelection, MSyntax::kBoolean); + syntax.addFlag(fsInvertSelection, flInvertSelection); + syntax.addFlag(fsLock, flLock, MSyntax::kBoolean); + syntax.addFlag(fsMergeSelection, flMergeSelection); + syntax.addFlag(fsPopSelected, flPopSelected); + syntax.addFlag(fsPopZeroSized, flPopZeroSized); + syntax.addFlag(fsRecomb, flRecomb); + syntax.addFlag(fsReplaceRest, flReplaceRest); + syntax.addFlag(fsRotateSelectionUp, flRotateSelectionUp); + syntax.addFlag(fsSplitSelection, flSplitSelection); + syntax.addFlag(fsToggleCollision, flToggleCollision); + syntax.addFlag(fsUndo, flUndo); +#ifdef GLOBAL_FALLBACK + syntax.addFlag(fsRedrawOnIdle, flRedrawOnIdle); + syntax.addFlag(fsFullRedrawOnIdle, flFullRedrawOnIdle); +#endif + return syntax; +} + + +MStatus shaveStyleCmd::doIt(const MArgList& argList) +{ + MStatus st; + MArgDatabase args(syntax(), argList, &st); + + if (!st) return st; + + // + // Is there a hair shape selected? + // + unsigned i; + MFnDagNode nodeFn; + unsigned numHairShapes = 0; + MDagPath targetPath; + MSelectionList selection; + MDagPath tempPath; +#ifdef GLOBAL_FALLBACK + if (args.isFlagSet(fsRedrawOnIdle)) + { + redrawOnIdle(false); + return MS::kSuccess; + } + else if (args.isFlagSet(fsFullRedrawOnIdle)) + { + redrawOnIdle(true); + return MS::kSuccess; + } +#endif + MGlobal::getActiveSelectionList(selection); + + for (i = 0; i < selection.length(); i++) + { + if (selection.getDagPath(i, tempPath) && tempPath.isValid()) + { + tempPath.extendToShape(); + nodeFn.setObject(tempPath); + + if (nodeFn.typeId() == shaveHairShape::id) + { + if (numHairShapes++ == 0) + targetPath = tempPath; + else + break; + } + } + } + + if (numHairShapes == 0 +#ifdef GLOBAL_FALLBACK + && !args.isFlagSet(fsFullRedrawOnIdle) && !args.isFlagSet(fsRedrawOnIdle) +#endif + ) + { + //////// debug /////////////// + if(args.isFlagSet(fsAttenuate)) displayError("Shave Attenuate."); + if(args.isFlagSet(fsLock)) displayError("Shave Lock."); + if(args.isFlagSet(fsMergeSelection)) displayError("Shave Merge Selection."); + if(args.isFlagSet(fsPopSelected)) displayError("Shave Pop Selected."); + if(args.isFlagSet(fsPopZeroSized)) displayError("Shave Pop Zerosized."); + if(args.isFlagSet(fsRecomb)) displayError("Shave Recomb."); + if(args.isFlagSet(fsReplaceRest)) displayError("Shave Replace Rest."); + if(args.isFlagSet(fsSplitSelection))displayError("Shave Split Selection."); + if(args.isFlagSet(fsToggleCollision))displayError("Shave Toggle Collision."); + if(args.isFlagSet(fsUndo)) displayError("Shave Undo."); +#ifdef GLOBAL_FALLBACK + if(args.isFlagSet(fsRedrawOnIdle)) displayError("Redraw higr res on idle."); + if(args.isFlagSet(fsFullRedrawOnIdle)) displayError("Force update and redraw higr res on idle."); +#endif + ////////////////////////////// + + displayError("No Shave node selected."); + + return MS::kFailure; + } + + if (numHairShapes > 1) + { + displayWarning( + "Multiple Shave nodes are selected:" + " only the first will be affected." + ); + } + + // + // Make sure that the shaveNode is loaded into the engine. + // + nodeFn.setObject(targetPath); + + shaveHairShape* hairShape = (shaveHairShape*)nodeFn.userNode(); + + hairShape->makeCurrent(); + hairShape->applySelections(); + + // + // Execute the command. + // + bool enable; + bool updateSelections = false; + + if (args.isFlagSet(fsAttenuate) + || args.isFlagSet(fsLock) + || args.isFlagSet(fsMergeSelection) + || args.isFlagSet(fsPopSelected) + || args.isFlagSet(fsPopZeroSized) + || args.isFlagSet(fsRecomb) + || args.isFlagSet(fsReplaceRest) + || args.isFlagSet(fsSplitSelection) + || args.isFlagSet(fsToggleCollision) + || args.isFlagSet(fsUndo)) + { + MGlobal::executeCommand("shave_prepareForEditing"); + + if (args.isFlagSet(fsAttenuate)) + SHAVEattenuate(); + else if (args.isFlagSet(fsLock)) + { + args.getFlagArgument(fsLock, 0, enable); + + if (enable) + SHAVElock(); + else + SHAVEunlock(); + } + else if (args.isFlagSet(fsPopSelected)) + SHAVEpop_selected(); + else if (args.isFlagSet(fsPopZeroSized)) + SHAVEpop_zero_sized(); + else if (args.isFlagSet(fsRecomb)) + SHAVErecomb(); + else if (args.isFlagSet(fsReplaceRest)) + SHAVEreplace_rest_interactive(); + else if (args.isFlagSet(fsToggleCollision)) + SHAVEtoggle_collision(); + else if (args.isFlagSet(fsUndo)) + SHAVEundo(); + else if (args.isFlagSet(fsSplitSelection)) + SHAVEsplit_selection(); + else if (args.isFlagSet(fsMergeSelection)) + SHAVEmerge_selection(); + + hairShape->applyEdits(true); + } + else if (args.isFlagSet(fsGrowSelection)) + { + SHAVEselect_grow(); + updateSelections = true; + } + else if (args.isFlagSet(fsHideSelection)) + { + args.getFlagArgument(fsHideSelection, 0, enable); + + if (enable) + hairShape->hideSelectedGuides(); + else + hairShape->unhideGuides(); + } + else if (args.isFlagSet(fsInvertSelection)) + { + invertSelection(); + updateSelections = true; + } + else if (args.isFlagSet(fsRotateSelectionUp)) + { + SHAVEselect_rotate_up(); + updateSelections = true; + } + //else if (args.isFlagSet(fsRedrawOnIdle)) + //{ + // redrawOnIdle(false); + //} + //else if (args.isFlagSet(fsFullRedrawOnIdle)) + //{ + // redrawOnIdle(true); + //} + + // + // Have the hair shape put it's component selections onto Maya's + // selection list. + // + if (updateSelections) hairShape->updateMayaComponentSelections(); + + return MS::kSuccess; +} + + +void shaveStyleCmd::invertSelection() +{ + // The behaviour of SHAVEselect_inverse isn't appropriate for tip + // selection mode: it turns off the tip and turns on all the other + // verts whereas if the tip is on we want it to turn off the entire + // guide. So we have to handle that mode ourselves. + MString selectType; + MGlobal::executeCommand("optionVar -q shaveBrushSelectMode", selectType); + + if (selectType == "tip") + { + SOFTGUIDE g; + int i; + + for (i = 0; SHAVEfetch_guide(i, &g) != -1; ++i) + { + g.select[0] = 1 - g.select[0]; + g.select[SHAVE_VERTS_PER_GUIDE-1] = g.select[0]; + SOFTput_guideSELECTONLY(i, &g); + } + } + else + { + SHAVEselect_inverse(); + } +} + +#ifdef GLOBAL_FALLBACK +//static LARGE_INTEGER now={ static_cast<LONGLONG>(0) }; +static qint64 now; + +bool shaveStyleCmd::redrawOnIdlDone = false; +void shaveStyleCmd::redrawOnIdle(bool fullUpdate) +{ + if(!redrawOnIdlDone) + { + if(IsMouseDown()) + { + redrawOnIdlDone = true; + return; + } + ////need some time intervall cut off to avoid flickering + //LARGE_INTEGER last = GetLastMoveTime(); + //QueryPerformanceCounter(&now); + + //LARGE_INTEGER freq; + //QueryPerformanceFrequency(&freq); + + //long long from_last = now.QuadPart - last.QuadPart; + //float t = (float)(from_last*1000.0/freq.QuadPart); + ////printf("t %f\n",t);fflush(stdout); + //if(t < 150.f /*&& !fullUpdate*/) + + now = GetQTimer().elapsed(); + qint64 t = now-GetLastMoveTime(); +// printf("t %i\n",(int)t);fflush(stdout); + + if(t < /*150*/300 /*|| QCoreApplication::hasPendingEvents()*/) + { + //redrawOnIdlDone = true; +// printf("refire \n");fflush(stdout); + + if(fullUpdate) + MGlobal::executeCommandOnIdle("shaveStyle -fullRedrawOnIdle"); + else + MGlobal::executeCommandOnIdle("shaveStyle -redrawOnIdle"); + return; + } + ////last = now; + SetLastMoveTime(now); + + MFnDagNode nodeFn; + MDagPathArray paths; + shaveUtil::getShaveNodes(paths); //it should not trigger ::compute + for (unsigned int i = 0; i < paths.length(); i++) + { + nodeFn.setObject(paths[i].node()); + + if (nodeFn.typeId() == shaveHairShape::id) + { + shaveHairShape* shape = (shaveHairShape*)nodeFn.userNode(); + shape->dirtyDisplay(); + shape->dirties.BRUSH_JUST_MOVED = 0; + shape->dirties.GLOBAL_MOUSE_DOWN = 0; + + /////// need to make sure that textures are connected /////// + shape->dirties.DIRTY_TEXTURE = 1; + shape->dirties.DIRTY_TEXTURE_JOE = 1; + ///////////////////////////////////////////////////////////// + + //////////////// + //shape->updateTexLookups(); + + if(fullUpdate) + { + //shape->makeCurrent(); + float trigger; + MPlug triggerPlug = nodeFn.findPlug("trigger"); + triggerPlug.getValue(trigger); + triggerPlug.setValue(trigger+1.0f); + + + } + + MHWRender::MRenderer::setGeometryDrawDirty(paths[i].node()); + } + } + + M3dView::active3dView().refresh(true,true); //is it needed? + + redrawOnIdlDone = true; + + //for (unsigned int i = 0; i < paths.length(); i++) + //{ + // nodeFn.setObject(paths[i].node()); + + // if (nodeFn.typeId() == shaveHairShape::id) + // { + // shaveHairShape* shape = (shaveHairShape*)nodeFn.userNode(); + // shape->dirtyDisplay(); + // + // } + //} + } +} + +unsigned int shaveStyleCmd::getTotalHaircount() +{ + return 0; +} +unsigned int shaveStyleCmd::getTotalDisplayMem() +{ + return 0; +} +#endif |