aboutsummaryrefslogtreecommitdiff
path: root/mayaPlug/shaveStyleCmd.cpp
diff options
context:
space:
mode:
authorBen Marsh <[email protected]>2019-10-22 09:07:59 -0400
committerBen Marsh <[email protected]>2019-10-22 09:07:59 -0400
commitbd0027e737c6512397f841c22786274ed74b927f (patch)
treef7ffbdb8f3741bb7f24635616cc189cba5cb865c /mayaPlug/shaveStyleCmd.cpp
downloadshave-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.cpp441
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