├── .gitignore ├── Makefile ├── README.md ├── icons ├── abouts.png ├── maya_icon.png ├── motionPathDraw.png └── motionPathEdit.png ├── include ├── BufferPath.h ├── CameraCache.h ├── ContextUtils.h ├── DrawUtils.h ├── GlobalSettings.h ├── KeyClipboard.h ├── Keyframe.h ├── MotionPath.h ├── MotionPathCmd.h ├── MotionPathDrawContext.h ├── MotionPathEditContext.h ├── MotionPathEditContextMenuWidget.h ├── MotionPathManager.h ├── MotionPathOverride.h ├── Vp2DrawUtils.h └── animCurveUtils.h ├── python └── tcMotionPath │ ├── __init__.py │ ├── icons │ ├── abouts.png │ ├── motionPathDraw.png │ └── motionPathEdit.png │ └── tcMotionPath.py └── source ├── BufferPath.cpp ├── CameraCache.cpp ├── ContextUtils.cpp ├── DrawUtils.cpp ├── GlobalSettings.cpp ├── KeyClipboard.cpp ├── Keyframe.cpp ├── MotionPath.cpp ├── MotionPathCmd.cpp ├── MotionPathDrawContext.cpp ├── MotionPathEditContext.cpp ├── MotionPathEditContextMenuWidget.cpp ├── MotionPathEditContextMenuWidgetMoc.cpp ├── MotionPathManager.cpp ├── MotionPathOverride.cpp ├── PluginMain.cpp ├── Vp2DrawUtils.cpp └── animCurveUtils.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | *.sdf 2 | *.opensdf 3 | *.pyc 4 | .project 5 | .cproject 6 | x64/ 7 | *.o 8 | Debug/ 9 | build/ 10 | *.exe 11 | *.msi 12 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #- 2 | # ========================================================================== 3 | # Copyright 1995,2006,2008 Autodesk, Inc. All rights reserved. 4 | # 5 | # Use of this software is subject to the terms of the Autodesk 6 | # license agreement provided at the time of installation or download, 7 | # or which otherwise accompanies this software in either electronic 8 | # or hard copy form. 9 | # ========================================================================== 10 | #+ 11 | NAME = tcMotionPath 12 | MAJOR = 1 13 | MINOR = 0.0 14 | VERSION = $(MAJOR).$(MINOR) 15 | 16 | LIBNAME = $(NAME).so 17 | 18 | C++ = g++412 19 | MAYAVERSION = 2015 20 | # Uncomment the following line on MIPSpro 7.2 compilers to supress 21 | # warnings about declarations in the X header files 22 | # WARNFLAGS = -woff 3322 23 | 24 | # When the following line is present, the linking of plugins will 25 | # occur much faster. If you link transitively (the default) then 26 | # a number of "ld Warning 85" messages will be printed by ld. 27 | # They are expected, and can be safely ignored. 28 | MAYA_LOCATION = /usr/autodesk/maya$(MAYAVERSION)-x64/ 29 | INSTALL_PATH = /home/alan/projects/deploy/maya/tcMotionPath/1.0/plug-ins/$(MAYAVERSION)/linux 30 | CFLAGS = -m64 -pthread -pipe -D_BOOL -DLINUX -DREQUIRE_IOSTREAM -Wno-deprecated -fno-gnu-keywords -fPIC -DUSE_PTHREADS -DUSE_LICENSE -O2 31 | C++FLAGS = $(CFLAGS) $(WARNFLAGS) 32 | INCLUDES = -I. -I$(MAYA_LOCATION)/include -I./include -I/home/alan/projects/build/include/libxml2 -I/home/alan/projects/build/include -I/home/alan/projects/build/include/LicenseClient 33 | LD = $(C++) -shared $(C++FLAGS) 34 | LIBS = -L$(MAYA_LOCATION)/lib -lOpenMaya -lOpenMayaAnim -lOpenMayaRender -lOpenMayaUI -L/home/alan/projects/build/lib -lLicenseClient -lSockets -lssl -lcrypto -lpthread -ldl 35 | 36 | .SUFFIXES: .cpp .cc .o .so .c 37 | 38 | .cc.o: 39 | $(C++) -c $(INCLUDES) $(C++FLAGS) $< 40 | 41 | .cpp.o: 42 | $(C++) -c $(INCLUDES) $(C++FLAGS) $< -o $@ 43 | 44 | .cc.i: 45 | $(C++) -E $(INCLUDES) $(C++FLAGS) $*.cc > $*.i 46 | 47 | .cc.so: 48 | -rm -f $@ 49 | $(LD) -o $@ $(INCLUDES) $< $(LIBS) 50 | 51 | .cpp.so: 52 | -rm -f $@ 53 | $(LD) -o $@ $(INCLUDES) $< $(LIBS) 54 | 55 | .o.so: 56 | -rm -f $@ 57 | $(LD) -o $@ $< $(LIBS) 58 | 59 | CPP_FILES := $(wildcard source/*.cpp) 60 | OBJS = $(addprefix source/,$(notdir $(CPP_FILES:.cpp=.o))) 61 | 62 | all: $(LIBNAME) 63 | @echo "Done" 64 | mv $(LIBNAME) $(INSTALL_PATH) 65 | 66 | $(LIBNAME): $(OBJS) 67 | -rm -f $@ 68 | $(LD) -o $@ $(OBJS) $(LIBS) 69 | 70 | depend: 71 | makedepend $(INCLUDES) -I/usr/include/CC *.cc 72 | 73 | clean: 74 | -rm -f source/*.o *.so 75 | 76 | Clean: 77 | -rm -f source/*.o *.so *.bak 78 | 79 | install: all 80 | mv $(LIBNAME) $(INSTALL_PATH) 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Maya Motion Path 2 | 3 | Our Motion Path tool is the ultimate solution for real-time visualization and editing of your animations in 3D space. 4 | 5 | ### Features: 6 | 7 | * Real-time motion path visualization 8 | * Camera and world space draw modes 9 | * Dockable GUI 10 | * Optional key frames visualization 11 | * Optional “Use Pivots” mode to take modified pivots into account 12 | * Optional key frame tangents visualization 13 | * Optional rotational key frame visualization 14 | * For objects with incoming connections, such as constraints or set driven keys, a baked/non-editable path is shown. 15 | * Lock selection 16 | * Interactive switch for lock selection 17 | * Motion path edit tool 18 | * Motion path draw tool 19 | * With the draw tool on, ctrl+click on a keyframe and drag to activate stroke mode. Closest: move the keys to the closest point on the drawn stroke; Spread: distributes keys uniformly along the drawn point 20 | * Multiple buffer curves 21 | * Buffer Curve to Nurb Curve feature 22 | * Copy 3D key frames positions inside the Maya viewport 23 | * World Paste 3D key frames positions onto other objects 24 | * Offset Paste 3D key frames positions onto other objects 25 | * Customizable settings, such as colors and sizes 26 | * Motion Path settings are saved in maya preferences 27 | * Stroke Mode (Ctrl + click a keyframe and drag with the draw context activated) 28 | 29 | If you are planning to use one of our tools in a studio, we would be grateful if you could let us know. 30 | 31 | ### Known limitations: 32 | 33 | * Please use Maya 2017 update 4 or the tool UI will freeze when docked in the Maya UI. Everything works as expected when the UI is not docked, even on earlier Maya updates. 34 | * Frames display does not show correctly On Linux (Viewport 2.0 ) 35 | * Weighted paths won’t display aligned-correct curve tangents when drawing using world space mode. Weighted paths won’t displayed tangents in camera space mode. 36 | * Key selection is not integrated fully with Maya undo, it won’t work in case of object deletions and similar actions. 37 | * Marquee selection in the MotionPathEditContext does not work with keys. 38 | * When locking selection, drawing the path for the locked object could be slow depending on the object hierarchy and connections. 39 | * Lock selection mode could be quite slow depending on the hierarchy/network of the locked object. 40 | * Rotational Keys are shown only in conjunction with one or more translation key frames. 41 | * With animation layers a baked/non-editable path will be shown. 42 | * Copy-Paste could not work as expected in some cases: 1) pasting keys on items with a different parent 2) when some world tangent info won’t be available from your source curves 3) when not copying all keys from the original curve 43 | * Copy-Paste only copies translation values, it DOES NOT work with rotations. 44 | 45 | ## License 46 | 47 | This project is licensed under [the LGPL license](http://www.gnu.org/licenses/). 48 | 49 | ## Contact us 50 | 51 | Please feel free to contact us at support@toolchefs.com in case you would like contribute or simply have questions. 52 | 53 | ### ENJOY! 54 | -------------------------------------------------------------------------------- /icons/abouts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Toolchefs/motionPath/1d02754694edddeca4f09ba057e2d92cc51674e1/icons/abouts.png -------------------------------------------------------------------------------- /icons/maya_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Toolchefs/motionPath/1d02754694edddeca4f09ba057e2d92cc51674e1/icons/maya_icon.png -------------------------------------------------------------------------------- /icons/motionPathDraw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Toolchefs/motionPath/1d02754694edddeca4f09ba057e2d92cc51674e1/icons/motionPathDraw.png -------------------------------------------------------------------------------- /icons/motionPathEdit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Toolchefs/motionPath/1d02754694edddeca4f09ba057e2d92cc51674e1/icons/motionPathEdit.png -------------------------------------------------------------------------------- /include/BufferPath.h: -------------------------------------------------------------------------------- 1 | // 2 | // BufferPath.h 3 | // MotionPath 4 | // 5 | // Created by Daniele Federico on 06/12/14. 6 | // 7 | // 8 | 9 | #ifndef BUFFERPATH_H 10 | #define BUFFERPATH_H 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | 23 | #include "GlobalSettings.h" 24 | #include "CameraCache.h" 25 | 26 | class BufferPath 27 | { 28 | public: 29 | BufferPath(); 30 | 31 | void draw(M3dView &view, CameraCache* cachePtr, MHWRender::MUIDrawManager* drawManager = NULL, const MHWRender::MFrameContext* frameContext = NULL); 32 | void setSelected(bool value){selected = value;}; 33 | void setMinTime(double value){minTime = value;}; 34 | void setFrames(std::vector value){frames=value;}; 35 | void setKeyFrames(std::map value){keyFrames=value;}; 36 | const std::vector* getFrames(){return &frames;}; 37 | 38 | private: 39 | void drawFrames(const double startTime, const double endTime, const MColor &curveColor, CameraCache* cachePtr, const MMatrix ¤tCameraMatrix, M3dView &view, MHWRender::MUIDrawManager* drawManager, const MHWRender::MFrameContext* frameContext); 40 | void drawKeyFrames(const double startTime, const double endTime, const MColor &curveColor, CameraCache* cachePtr, const MMatrix ¤tCameraMatrix, M3dView &view, MHWRender::MUIDrawManager* drawManager, const MHWRender::MFrameContext* frameContext); 41 | 42 | std::vector frames; 43 | std::map keyFrames; 44 | bool selected; 45 | MColor black; 46 | double minTime; 47 | 48 | }; 49 | 50 | typedef std::map::iterator BPKeyframeIterator; 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /include/CameraCache.h: -------------------------------------------------------------------------------- 1 | // 2 | // CameraCache.h 3 | // MotionPath 4 | // 5 | // Created by Daniele Federico on 11/05/15. 6 | // 7 | // 8 | 9 | #ifndef MotionPath_CameraCache_h 10 | #define MotionPath_CameraCache_h 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | 20 | class CameraCache 21 | { 22 | public: 23 | CameraCache(); 24 | ~CameraCache(){} 25 | 26 | std::map matrixCache; 27 | //std::map projMatrixCache; 28 | int portWidth; 29 | int portHeight; 30 | 31 | bool isCaching(){return caching;} 32 | bool isInitialized(){return initialized;} 33 | 34 | void initialize(const MObject &camera); 35 | 36 | void cacheCamera(); 37 | void ensureMatricesAtTime(const double time, const bool force=false); 38 | void checkRangeIsCached(); 39 | 40 | private: 41 | bool caching, initialized; 42 | MPlug worldMatrixPlug; 43 | MPlug txPlug, tyPlug, tzPlug; 44 | MPlug rxPlug, ryPlug, rzPlug; 45 | }; 46 | 47 | typedef std::map CameraCacheMap; 48 | typedef std::map::iterator CameraCacheMapIterator; 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /include/ContextUtils.h: -------------------------------------------------------------------------------- 1 | // 2 | // ContextUtils.h 3 | // MotionPath 4 | // 5 | // Created by Daniele Federico on 29/11/14. 6 | // 7 | // 8 | 9 | #ifndef CONTEXTUTILS_H 10 | #define CONTEXTUTILS_H 11 | 12 | #include "MotionPathManager.h" 13 | #include "MotionPath.h" 14 | 15 | #include 16 | #include 17 | 18 | namespace contextUtils 19 | { 20 | bool worldCameraSpaceToWorldSpace(MVector &position, M3dView &view, const double time, const MMatrix &inverseCameraMatrix, MotionPathManager &mpManager); 21 | bool worldCameraSpaceToWorldSpace(MPoint &position, M3dView &view, const double time, const MMatrix &inverseCameraMatrix, MotionPathManager &mpManager); 22 | 23 | MVector getWorldPositionFromProjPoint(const MVector &pointToMove, const double initialX, const double initialY, const double currentX, const double currentY, const M3dView &view, const MVector &cameraPosition); 24 | 25 | int processCurveHits(M3dView &view, CameraCache *cachePtr, MotionPathManager &mpManager); 26 | void processTangentHits(MotionPath* motionPathPtr, M3dView &view, CameraCache *cachePtr, int &selectedKeyId, int &selectedTangent); 27 | void processKeyFrameHits(MotionPath* motionPathPtr, M3dView &view, CameraCache *cachePtr, MIntArray &selectedKeys); 28 | bool processFramesHits(MotionPath* motionPathPtr, M3dView &view, CameraCache *cachePtr, double &time); 29 | 30 | int processCurveHits(const short mx, const short my, const MMatrix &cameraMatrix, M3dView &view, CameraCache *cachePtr, MotionPathManager &mpManager); 31 | void processTangentHits(const short mx, const short my, MotionPath* motionPathPtr, M3dView &view, const MMatrix &cameraMatrix, CameraCache *cachePtr, int &selectedKeyId, int &selectedTangent); 32 | void processKeyFrameHits(const short mx, const short my, MotionPath* motionPathPtr, M3dView &view, const MMatrix &cameraMatrix, CameraCache *cachePtr, MIntArray &selectedKeys); 33 | bool processFramesHits(const short mx, const short my, MotionPath* motionPathPtr, M3dView &view, const MMatrix &cameraMatrix, CameraCache *cachePtr, double &time); 34 | 35 | void refreshSelectionMethod(MEvent &event, MGlobal::ListAdjustment &listAdjustment); 36 | void drawMarqueeGL(short initialX, short initialY, short finalX, short finalY); 37 | void drawMarquee(MHWRender::MUIDrawManager& drawMgr, short initialX, short initialY, short finalX, short finalY); 38 | void applySelection(short initialX, short initialY, short finalX, short finalY, const MGlobal::ListAdjustment &listAdjustment); 39 | 40 | } 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /include/DrawUtils.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef DRAWUTILS_H 3 | #define DRAWUTILS_H 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | #ifdef __APPLE__ 15 | #include 16 | #include 17 | #else 18 | #include 19 | #include 20 | #endif 21 | 22 | #include 23 | #include 24 | 25 | namespace drawUtils 26 | { 27 | void drawLineStipple(const MVector &origin, const MVector &target, float lineWidth, const MColor &color); 28 | 29 | void drawLine(const MVector &origin, const MVector &target, float lineWidth); 30 | 31 | void drawLineWithColor(const MVector &origin, const MVector &target, float lineWidth, const MColor &color); 32 | 33 | void drawPoint(const MVector &point, float size); 34 | 35 | void drawPointWithColor(const MVector &point, float size, const MColor &color); 36 | 37 | void drawKeyFramePoints(KeyframeMap &keyframesCache, const float size, const double colorMultiplier, const int portWidth, const int portHeight, const bool showRotationKeyframes); 38 | 39 | void drawKeyFrames(std::vector keys, const float size, const double colorMultiplier,const int portWidth, const int portHeight, const bool showRotationKeyframes); 40 | 41 | void convertWorldSpaceToCameraSpace(CameraCache* cachePtr, std::map &positions, std::map &screenSpacePositions); 42 | 43 | void drawFrameLabel(double frame, const MVector &framePos, M3dView &view, const double sizeOffset, const MColor &color, const MMatrix &refMatrix); 44 | /* 45 | void drawCameraSpaceFrames(CameraCache* cachePtr, const MColor &color, std::map &positions, const double startFrame, const double endFrame); 46 | 47 | void drawCameraSpacePointWithColor(CameraCache *cachePtr, const MColor &color, const MPoint &position, const double size); 48 | 49 | void convertKeyFrameTangentsToCameraSpace(CameraCache *cachePtr, KeyframeMap &keyframesCache, const MMatrix ¤tCameraMatrix); 50 | 51 | void drawCameraSpaceKeyFrameTangents(CameraCache *cachePtr, KeyframeMap &keyframesCache); 52 | 53 | void drawCameraSpaceFramesForSelection(M3dView &view, CameraCache *cachePtr, std::map &frameScreenSpacePositions); 54 | 55 | void drawCameraSpaceKeyFramesForSelection(M3dView &view, CameraCache *cachePtr, KeyframeMap &keyframesCache); 56 | 57 | void drawCameraSpaceKeyFrameTangentsForSelection(M3dView &view, CameraCache *cachePtr, KeyframeMap &keyframesCache); 58 | */ 59 | } 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /include/GlobalSettings.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef GLOBALSETTINGS_H 3 | #define GLOBALSETTINGS_H 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | class GlobalSettings 11 | { 12 | public: 13 | enum DrawMode{ 14 | kWorldSpace = 0, 15 | kCameraSpace = 1}; 16 | 17 | static double startTime; 18 | static double endTime; 19 | static double framesBack; 20 | static double framesFront; 21 | static MColor pathColor; 22 | static MColor currentFrameColor; 23 | static MColor tangentColor; 24 | static MColor brokenTangentColor; 25 | static MColor bufferPathColor; 26 | static MColor weightedPathTangentColor; 27 | static MColor weightedPathColor; 28 | static MColor frameLabelColor; 29 | static double pathSize; 30 | static double frameSize; 31 | static bool showTangents; 32 | static bool showKeyFrames; 33 | static bool showKeyFrameNumbers; 34 | static bool showFrameNumbers; 35 | static bool showRotationKeyFrames; 36 | static bool showPath; 37 | static double drawTimeInterval; 38 | static int drawFrameInterval; 39 | static MMatrix cameraMatrix; 40 | static int portWidth; 41 | static int portHeight; 42 | static bool lockedMode; 43 | static bool enabled; 44 | static bool alternatingFrames; 45 | static bool lockedModeInteractive; 46 | static bool usePivots; 47 | static int strokeMode; 48 | static DrawMode motionPathDrawMode; 49 | }; 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /include/KeyClipboard.h: -------------------------------------------------------------------------------- 1 | // 2 | // KeyClipboard.h 3 | // MotionPath 4 | // 5 | // Created by Daniele Federico on 25/01/15. 6 | // 7 | // 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | #include 15 | 16 | #ifndef __MotionPath__KeyClipboard__ 17 | #define __MotionPath__KeyClipboard__ 18 | 19 | class KeyCopy 20 | { 21 | public: 22 | KeyCopy(); 23 | 24 | void copyKeyTangentStatus(MFnAnimCurve &curve, unsigned int keyId, const Keyframe::Axis axis); 25 | void addKeyFrame(MFnAnimCurve &cx, MFnAnimCurve &cy, MFnAnimCurve &cz, const MTime &time, const MVector &pos, const bool isBoundary, MAnimCurveChange *change); 26 | void setTangents(MFnAnimCurve &cx, MFnAnimCurve &cy, MFnAnimCurve &cz, const MMatrix &pMatrix, const MTime &time, const bool isBoundary, const bool modifyInTangent, const bool modifyOutTangent, const bool breakTangentsX, const bool breakTangentsY, const bool breakTangentsZ, const bool xWasWeighted, const bool yWasWeighted, const bool zWasWeighted, MAnimCurveChange *change); 27 | void setTangent(MFnAnimCurve &curve, const float value, const unsigned int keyID, const double weight, const float x, const bool inTangent, const bool wasWeighted, MAnimCurveChange *change); 28 | 29 | double deltaTime; 30 | MVector worldPos; 31 | MVector inWorldTangent; 32 | MVector outWorldTangent; 33 | MVector inWeightedWorldTangent; 34 | MVector outWeightedWorldTangent; 35 | 36 | bool hasKeyX, hasKeyY, hasKeyZ; 37 | MFnAnimCurve::TangentType tinX, tinY, tinZ; 38 | MFnAnimCurve::TangentType toutX, toutY, toutZ; 39 | bool tangentsLockedX, tangentsLockedY, tangentsLockedZ; 40 | bool weightsLockedX, weightsLockedY, weightsLockedZ; 41 | 42 | #if defined(MAYA2018) 43 | MFnAnimCurve::TangentValue xInX, xOutX, xInY, xOutY, xInZ, xOutZ; 44 | #else 45 | float xInX, xOutX, xInY, xOutY, xInZ, xOutZ; 46 | #endif 47 | double wInX, wOutX, wInY, wOutY, wInZ, wOutZ; 48 | }; 49 | 50 | class KeyClipboard 51 | { 52 | public: 53 | static KeyClipboard& getClipboard(){static KeyClipboard clipboard; return clipboard;} 54 | 55 | void clearClipboard(){keys.clear();}; 56 | void setClipboardSize(int size){keys.reserve(size);}; 57 | void addKey(KeyCopy key){keys.push_back(key);}; 58 | int getSize(){return keys.size();}; 59 | KeyCopy *keyCopyAt(const int index){return &keys[index];}; 60 | 61 | void setXWeighted(bool value){xWeighted = value;}; 62 | void setYWeighted(bool value){yWeighted = value;}; 63 | void setZWeighted(bool value){zWeighted = value;}; 64 | 65 | bool isXWeighed(){return xWeighted;}; 66 | bool isYWeighed(){return yWeighted;}; 67 | bool isZWeighed(){return zWeighted;}; 68 | 69 | private: 70 | KeyClipboard() {}; 71 | std::vector keys; 72 | bool xWeighted, yWeighted, zWeighted; 73 | }; 74 | 75 | 76 | #endif /* defined(__MotionPath__KeyClipboard__) */ 77 | -------------------------------------------------------------------------------- /include/Keyframe.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef KEYFRAME_H 3 | #define KEYFRAME_H 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | #include "GlobalSettings.h" 19 | 20 | class Keyframe 21 | { 22 | public: 23 | enum Axis{ 24 | kAxisX = 0, 25 | kAxisY = 1, 26 | kAxisZ = 2}; 27 | 28 | enum Tangent{ 29 | kOutTangent = 0, 30 | kInTangent = 1}; 31 | 32 | Keyframe(); 33 | bool hasTranslationXYZ(); 34 | bool hasRotationXYZ(); 35 | void setTangent(int keyIndex, const MFnAnimCurve &curve, const Keyframe::Axis &axisName, const Keyframe::Tangent &tangentName); 36 | void setTangentValue(double value, const Keyframe::Axis &axisName, const Keyframe::Tangent &tangentName); 37 | void setKeyId(int id, const Keyframe::Axis &axisName); 38 | void setRotKeyId(int id, const Keyframe::Axis &axisName); 39 | 40 | void getKeyTranslateAxis(std::vector &axis); 41 | void getKeyRotateAxis(std::vector &axis); 42 | 43 | static void getColorForAxis(const Keyframe::Axis axis, MColor &color); 44 | 45 | void setSelectedFromTool(bool value){selectedFromTool = value;}; 46 | 47 | int id; 48 | MVector position; 49 | MVector worldPosition; 50 | MVector projPosition; 51 | double time; 52 | bool tangentsLocked; 53 | bool showInTangent; 54 | bool showOutTangent; 55 | int xKeyId; 56 | int yKeyId; 57 | int zKeyId; 58 | 59 | int xRotKeyId; 60 | int yRotKeyId; 61 | int zRotKeyId; 62 | 63 | MVector inTangent; 64 | MVector outTangent; 65 | MVector inTangentWorld; 66 | MVector outTangentWorld; 67 | MVector inTangentWorldFromCurve; 68 | MVector outTangentWorldFromCurve; 69 | 70 | bool selectedFromTool; 71 | }; 72 | 73 | typedef std::map KeyframeMap; 74 | typedef std::map::iterator KeyframeMapIterator; 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /include/MotionPath.h: -------------------------------------------------------------------------------- 1 | // 2 | // MotionPath.h 3 | // MotionPath 4 | // 5 | // Created by Daniele Federico on 11/11/14. 6 | // 7 | // 8 | 9 | #ifndef MOTIONPATH_H 10 | #define MOTIONPATH_H 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | #include 30 | #include 31 | #include "KeyClipboard.h" 32 | #include "CameraCache.h" 33 | 34 | #include 35 | 36 | class MotionPath 37 | { 38 | public: 39 | MotionPath(const MObject &object); 40 | ~MotionPath(); 41 | 42 | MObject& object(){return thisObject;}; 43 | 44 | bool isCacheDone(){return this->cacheDone;}; 45 | void setTimeRange(double startTime, double endTime); 46 | void setDisplayTimeRange(double start, double end); 47 | void growParentAndPivotMatrixCache(double time, double expansion); 48 | void draw(M3dView &view, CameraCache* cachePtr, MHWRender::MUIDrawManager* drawManager = NULL, const MHWRender::MFrameContext* frameContext = NULL); 49 | 50 | bool isConstrained(){return constrained;}; 51 | 52 | void selectKeyAtTime(const double time){selectedKeyTimes.insert(time);}; 53 | void deselectAllKeys(){selectedKeyTimes.clear();}; 54 | void deselectKeyAtTime(const double time){if (isKeyAtTimeSelected(time)) selectedKeyTimes.erase(time);}; 55 | void selectAllKeys(); 56 | void invertKeysSelection(); 57 | bool isKeyAtTimeSelected(const double time){return selectedKeyTimes.find(time)!=selectedKeyTimes.end();}; 58 | MDoubleArray getSelectedKeys(); 59 | MDoubleArray getKeys(); 60 | 61 | void setSelectedFromTool(bool value){selectedFromTool = value;}; 62 | void setColorMultiplier(double colorMultiplier){this->colorMultiplier = colorMultiplier;}; 63 | 64 | //void drawWorldSpace(M3dView &view, CameraCache* cachePtr, const bool selecting); 65 | //void drawCameraSpace(M3dView &view, CameraCache* cachePtr, const bool selecting); 66 | void drawPath(M3dView &view, CameraCache* cachePtr, const MMatrix ¤tCameraMatrix, const bool selecting, MHWRender::MUIDrawManager* drawManager = NULL, const MHWRender::MFrameContext* frameContext = NULL); 67 | 68 | void drawCurvesForSelection(M3dView &view, CameraCache* cachePtr); 69 | void drawTangentsForSelection(M3dView &view, CameraCache *cachePtr); 70 | void drawKeysForSelection(M3dView &view, CameraCache* cachePtr); 71 | void drawFramesForSelection(M3dView &view, CameraCache* cachePtr); 72 | 73 | void getTangentHandleWorldPosition(const double keyTime, const Keyframe::Tangent &tangentName, MVector &tangentWorldPosition); 74 | void getKeyWorldPosition(const double keyTime, MVector &keyWorldPosition); 75 | double getTimeFromKeyId(const int id); 76 | void deleteKeyFrameWithId(const int id, MAnimCurveChange *change); 77 | void addKeyFrameAtTime(const double time, MAnimCurveChange *change, MVector *position=NULL, bool useCache=true); 78 | void deleteKeyFrameAtTime(const double time, MAnimCurveChange *change, const bool useCache=true); 79 | 80 | void offsetWorldPosition(const MVector &offset, const double time, MAnimCurveChange *change); 81 | void setFrameWorldPosition(const MVector &position, const double time, MAnimCurveChange *change); 82 | void setTangentWorldPosition(const MVector &position, const double time, Keyframe::Tangent tangentId, const MMatrix &toWorldMatrix, MAnimCurveChange *change); 83 | void rotateTangentWorldPositionAroundAxis(const double angle, const MVector &axis, const double stretch, const double time, Keyframe::Tangent tangentId, MAnimCurveChange *change); 84 | static void setTangentValue(float value, int key, MFnAnimCurve &curve, Keyframe::Tangent tangentName, const MTime &time, MAnimCurveChange *change); 85 | 86 | void copyKeyFrameFromTo(const double from, const double to, const MVector &cachedPosition, MAnimCurveChange *change); 87 | 88 | void deleteAllKeyFramesAfterTime(const double time, MAnimCurveChange *change); 89 | void deleteKeyFramesBetweenTimes(const double startTime, const double endTime, MFnAnimCurve &curve, MAnimCurveChange *change); 90 | 91 | void getBoundariesForTime(const double time, double *minBoundary, double *maxBoundary); 92 | int getNumKeyFrames(); 93 | MVector getPos(double time); 94 | MVector getWorldPositionAtTime(const double time); 95 | 96 | void clearParentMatrixCache(); 97 | void cacheParentMatrixRange(); 98 | 99 | void setIsDrawing(const bool value){isDrawing = value;}; 100 | void setEndrawingTime(const double value){endDrawingTime = value;}; 101 | 102 | BufferPath createBufferPath(); 103 | 104 | static bool hasAnimationLayers(const MObject &object); 105 | 106 | void storeSelectedKeysInClipboard(); 107 | void pasteKeys(const double time, const bool offset); 108 | 109 | static MVector multPosByParentMatrix(const MVector &vec, const MMatrix &mat); 110 | 111 | static MMatrix getMatrixFromPlug(const MPlug &matrixPlug, const MTime &t); 112 | 113 | void addWorldMatrixCallback(); 114 | void removeWorldMartrixCallback(); 115 | 116 | bool getWorldSpaceCallbackCalled(); 117 | void setWorldSpaceCallbackCalled(const bool value, const MObject &tempAncestorNode); 118 | 119 | KeyframeMap *keyFramesCachePtr() { return &keyframesCache; } 120 | void getFramePositions(std::vector> &vec); 121 | 122 | private: 123 | 124 | MObject thisObject; 125 | MPlug txPlug, tyPlug, tzPlug, rxPlug, ryPlug, rzPlug; 126 | double startTime, endTime; 127 | double displayStartTime, displayEndTime; 128 | double startTimeCached, endTimeCached; 129 | double colorMultiplier; 130 | bool constrained; 131 | bool selectedFromTool; 132 | MPlug pMatrixPlug; 133 | std::map pMatrixCache; 134 | bool cacheDone; 135 | bool worldSpaceCallbackCalled; 136 | KeyframeMap keyframesCache; 137 | 138 | MCallbackId worldMatrixCallbackId; 139 | 140 | MObject tempAncestorNode; 141 | 142 | std::map frameScreenSpacePositions; 143 | 144 | //Pivot stuff 145 | MPlug rpxPlug, rpyPlug, rpzPlug, rptxPlug, rptyPlug, rptzPlug; 146 | // 147 | 148 | bool isWeighted; 149 | 150 | std::set selectedKeyTimes; 151 | 152 | bool isDrawing; 153 | double endDrawingTime; 154 | 155 | void ensureParentAndPivotMatrixAtTime(const double time); 156 | MMatrix getPMatrixAtTime(const MTime &evalTime); 157 | MMatrix getPivotMatrix(const MTime &evalTime); 158 | MVector getVectorFromPlugs(const MTime &evalTime, const MPlug &x, const MPlug &y, const MPlug &z); 159 | 160 | bool isCurveTypeAnimatable(MFnAnimCurve::AnimCurveType type); 161 | bool isConstrained(const MFnDagNode &dagNodeFn); 162 | void findParentMatrixPlug(const MObject &transform, const bool isConstrained, MPlug &matrixPlug); 163 | void findPivotPlugs(MFnDependencyNode &depNodFn); 164 | void expandKeyFramesCache(const MFnAnimCurve &curve, const Keyframe::Axis &axisName, bool isTranslate); 165 | void cacheKeyFrames(const MFnAnimCurve &curveTX, const MFnAnimCurve &curveTY, const MFnAnimCurve &curveTZ, const MFnAnimCurve &curveRX, const MFnAnimCurve &curveRY, const MFnAnimCurve &curveRZ, CameraCache* cachePtr, const MMatrix ¤tCameraMatrix); 166 | void setShowInOutTangents(const MFnAnimCurve &curveTX, const MFnAnimCurve &curveTY, const MFnAnimCurve &curveTZ); 167 | bool showTangent(const double time, const int firstId, const double firstTime, const int secondId, const double secondTime); 168 | 169 | void copyKeyFrameFromToOnCurve(MFnAnimCurve &curve, int keyId, double value, double time, MAnimCurveChange *change); 170 | 171 | void deleteKeyFramesAfterTime(const double time, MFnAnimCurve &curve, MAnimCurveChange *change); 172 | 173 | void drawFrames(CameraCache* cachePtr, const MMatrix ¤tCameraMatrix, M3dView &view, MHWRender::MUIDrawManager* drawManager, const MHWRender::MFrameContext* frameContext); 174 | void drawFrame(const double time, const MVector &pos, const MColor &color, double alpha, M3dView &view, MMatrix ¤tCameraMatrix, MHWRender::MUIDrawManager* drawManager, const MHWRender::MFrameContext* frameContext); 175 | void drawCurrentFrame(CameraCache* cachePtr, const MMatrix ¤tCameraMatrix, M3dView &view, MHWRender::MUIDrawManager* drawManager, const MHWRender::MFrameContext* frameContext); 176 | void drawKeyFrames(CameraCache *cachePtr, MMatrix ¤tCameraMatrix, MHWRender::MUIDrawManager* drawManager, const MHWRender::MFrameContext* frameContext); 177 | void drawTangents(M3dView &view, MMatrix ¤tCameraMatrix, MHWRender::MUIDrawManager* drawManager, const MHWRender::MFrameContext* frameContext); 178 | void drawFrameLabels(M3dView &view, CameraCache* cachePtr, const MMatrix ¤tCameraMatrix, MHWRender::MUIDrawManager* drawManager, const MHWRender::MFrameContext* frameContext); 179 | 180 | /*void drawCameraSpaceFrames(CameraCache* cachePtr, std::map &framePositions, std::map &frameScreenSpacePositions, const MMatrix ¤tCameraMatrix); 181 | void drawCameraSpaceCurrentFrame(CameraCache* cachePtr, std::map &frameScreenSpacePositions,const double currentTimeValue); 182 | void drawCameraSpaceFrameLabels(M3dView view, CameraCache* cachePtr, const MMatrix ¤tCamerMatrix, std::map &positions, std::map &screenSpacePositions); 183 | void drawCameraSpaceKeyFrames(CameraCache* cachePtr, std::vectorkeys); 184 | void convertKeyFramesInCameraSpace(CameraCache* cachePtr, std::map &framePositions, std::map &frameScreenSpacePositions, const MMatrix ¤tCameraMatrix, std::vector &keys); 185 | void drawCameraSpaceTangents(CameraCache* cachePtr, const MMatrix ¤tCameraMatrix); 186 | */ 187 | 188 | int getMinTime(MFnAnimCurve &curveX, MFnAnimCurve &curveY, MFnAnimCurve &curveZ); 189 | int getMaxTime(MFnAnimCurve &curveX, MFnAnimCurve &curveY, MFnAnimCurve &curveZ); 190 | void expandeBufferPathKeyFrames(MFnAnimCurve &curve, std::map &keyFrames); 191 | 192 | static void worldMatrixChangedCallback(MObject& transformNode, MDagMessage::MatrixModifiedFlags& modified, void* data); 193 | void cacheParentMatrixRangeForWorldCallback(MObject &transformNode); 194 | 195 | }; 196 | 197 | #endif 198 | -------------------------------------------------------------------------------- /include/MotionPathCmd.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef MOTIONPATHCMD_H 3 | #define MOTIONPATHCMD_H 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "MotionPathManager.h" 15 | #include "GlobalSettings.h" 16 | 17 | class MotionPathCmd: public MPxCommand 18 | { 19 | public: 20 | MotionPathCmd(); 21 | ~MotionPathCmd(); 22 | 23 | MStatus doIt(const MArgList&); 24 | bool isUndoable() const; 25 | MStatus undoIt(); 26 | MStatus redoIt(); 27 | 28 | static MSyntax syntaxCreator(); 29 | 30 | static void* creator(); 31 | 32 | private: 33 | bool animUndoable; 34 | MAnimCurveChange* animCurveChangePtr; 35 | 36 | bool dgUndoable; 37 | MDGModifier *dgModifierPtr; 38 | 39 | bool keySelectionUndoable; 40 | std::vector initialSelection; 41 | std::vector finalSelection; 42 | 43 | bool selectionUndoable; 44 | MSelectionList newSelection, oldSelection; 45 | 46 | void restoreKeySelection(const std::vector &sel); 47 | 48 | MColor parseColorArg(const MArgList& args); 49 | bool createCurveFromBufferPath(BufferPath *bp); 50 | 51 | }; 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /include/MotionPathDrawContext.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef MOTIONPATHDRAWCONTEXT_H 4 | #define MOTIONPATHDRAWCONTEXT_H 5 | 6 | #include "MotionPathManager.h" 7 | #include "MotionPath.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | #include 26 | 27 | class MotionPathDrawContextCmd: public MPxContextCommand 28 | { 29 | public: 30 | virtual MPxContext* makeObj(); 31 | 32 | public: 33 | static void* creator(); 34 | }; 35 | 36 | class MotionPathDrawContext: public MPxContext 37 | { 38 | public: 39 | enum DrawMode{ 40 | kNoneMode = 0, 41 | kClickAddWorld = 1, 42 | kDraw = 2, 43 | kStroke = 3 44 | }; 45 | 46 | MotionPathDrawContext(); 47 | 48 | virtual MStatus doPress(MEvent &event); 49 | virtual MStatus doDrag(MEvent &event); 50 | virtual MStatus doRelease(MEvent &event); 51 | 52 | virtual MStatus doPress(MEvent & event, MHWRender::MUIDrawManager& drawMgr, const MHWRender::MFrameContext& context); 53 | virtual MStatus doDrag(MEvent & event, MHWRender::MUIDrawManager& drawMgr, const MHWRender::MFrameContext& context); 54 | virtual MStatus doRelease(MEvent & event, MHWRender::MUIDrawManager& drawMgr, const MHWRender::MFrameContext& context); 55 | 56 | virtual void toolOnSetup(MEvent& event); 57 | virtual void toolOffCleanup(); 58 | 59 | private: 60 | void drawStroke(); 61 | void drawStrokeNew(MHWRender::MUIDrawManager& drawMgr); 62 | bool doPressCommon(MEvent &event, const bool old); 63 | bool doDragCommon(MEvent &event, const bool old); 64 | bool doReleaseCommon(MEvent &event, const bool old); 65 | 66 | int getStrokeDirection(MVector directionalVector, const MDoubleArray &keys, const int selectedIndex); 67 | MVector getkeyScreenPosition(const double index); 68 | MVector getClosestPointOnPolyLine(const MVector &q); 69 | MVector getSpreadPointOnPolyLine(const int i, const int pointSize, const double strokeLenght, const std::vector &segmentLenghts); 70 | 71 | MotionPath* selectedMotionPathPtr; 72 | DrawMode currentMode; 73 | 74 | MGlobal::ListAdjustment listAdjustment; 75 | 76 | MVectorArray strokePoints; 77 | 78 | M3dView activeView; 79 | bool fsDrawn; 80 | 81 | short initialX, initialY, finalX, finalY; 82 | double selectedTime; 83 | int selectedKeyId; 84 | MVector keyWorldPosition; 85 | MPoint cameraPosition; 86 | 87 | MMatrix inverseCameraMatrix; 88 | 89 | double maxTime; 90 | double steppedTime; 91 | clock_t initialClock; 92 | }; 93 | 94 | typedef struct st_StrokeCache 95 | { 96 | MVector screenPosition; 97 | MVector originalScreenPosition; 98 | MVector originalWorldPosition; 99 | double time; 100 | } StrokeCache; 101 | 102 | #endif 103 | -------------------------------------------------------------------------------- /include/MotionPathEditContext.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef MOTIONPATHEDITCONTEXT_H 4 | #define MOTIONPATHEDITCONTEXT_H 5 | 6 | #include "MotionPathEditContextMenuWidget.h" 7 | #include "MotionPathManager.h" 8 | #include "MotionPath.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include 26 | #include 27 | 28 | class MotionPathEditContextCmd: public MPxContextCommand 29 | { 30 | public: 31 | MotionPathEditContextCmd(); 32 | virtual MPxContext* makeObj(); 33 | static void* creator(); 34 | }; 35 | 36 | class MotionPathEditContext: public MPxContext 37 | { 38 | public: 39 | enum EditMode{ 40 | kNoneMode = 0, 41 | kFrameEditMode = 1, 42 | kTangentEditMode = 2, 43 | kShiftKeyMode = 3}; 44 | 45 | MotionPathEditContext(); 46 | ~MotionPathEditContext(); 47 | 48 | virtual MStatus doPress(MEvent &event); 49 | virtual MStatus doDrag(MEvent &event); 50 | virtual MStatus doRelease(MEvent &event); 51 | 52 | virtual MStatus doPress(MEvent & event, MHWRender::MUIDrawManager& drawMgr, const MHWRender::MFrameContext& context); 53 | virtual MStatus doDrag(MEvent & event, MHWRender::MUIDrawManager& drawMgr, const MHWRender::MFrameContext& context); 54 | virtual MStatus doRelease(MEvent & event, MHWRender::MUIDrawManager& drawMgr, const MHWRender::MFrameContext& context); 55 | 56 | virtual void toolOnSetup(MEvent& event); 57 | virtual void toolOffCleanup(); 58 | 59 | 60 | private: 61 | int findPrefEditAxisFromVector(const MVector vec); 62 | 63 | void modifySelection(const MDoubleArray &selectedTimes, const bool ctrl, const bool shift); 64 | 65 | bool doPressCommon(MEvent &event, const bool old); 66 | void doDragCommon(MEvent &event, const bool old); 67 | void doReleaseCommon(MEvent &event, const bool old); 68 | 69 | MotionPath* selectedMotionPathPtr; 70 | EditMode currentMode; 71 | 72 | bool startedRecording; 73 | 74 | MGlobal::ListAdjustment listAdjustment; 75 | 76 | bool alongPreferredAxis; 77 | int prefEditAxis; 78 | 79 | bool shiftCachedDone; 80 | 81 | short initialX, initialY; 82 | short finalX, finalY; 83 | 84 | double lastSelectedTime; 85 | int selectedTangentId; 86 | MVector tangentWorldPosition; 87 | MVector keyWorldPosition; 88 | MVector lastWorldPosition; 89 | MPoint cameraPosition; 90 | 91 | M3dView activeView; 92 | bool fsDrawn; 93 | 94 | MMatrix inverseCameraMatrix; 95 | 96 | ContextMenuWidget* ctxMenuWidget; 97 | }; 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /include/MotionPathEditContextMenuWidget.h: -------------------------------------------------------------------------------- 1 | // 2 | // MotionPathEditContextMenuWidget.h 3 | // MotionPath 4 | // 5 | // Created by Daniele Federico on 24/01/15. 6 | // 7 | // 8 | 9 | #ifndef __MotionPath__MotionPathEditContextMenuWidget__ 10 | #define __MotionPath__MotionPathEditContextMenuWidget__ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | /* TO GENERATE THE MOC FILE ON A MAC 18 | /Applications/Autodesk/maya2015/Maya.app/Contents/bin/moc -I "/Applications/Autodesk/maya2015/devkit/include/:/Applications/Autodesk/maya2015/devkit/include/qt-include" MotionPathEditContextMenuWidget.h -o MotionPathEditContextMenuWidgetMoc.cpp 19 | */ 20 | 21 | class ContextMenuWidget : public QWidget 22 | { 23 | Q_OBJECT 24 | 25 | public: 26 | ContextMenuWidget(QWidget *parent = 0); 27 | ~ContextMenuWidget(); 28 | 29 | public slots: 30 | void menuAction(QAction *action); 31 | 32 | protected: 33 | bool eventFilter(QObject *o, QEvent *e); 34 | 35 | 36 | private: 37 | 38 | void refreshSelection(const QPoint point); 39 | 40 | bool frame, keyframe, curve; 41 | int selectedCurveId; 42 | MIntArray selectedKeys; 43 | double frameTime; 44 | 45 | QWidget *m_parent; 46 | QPointer m_menu; 47 | }; 48 | 49 | #endif /* defined(__MotionPath__MotionPathEditContextMenuWidget__) */ 50 | -------------------------------------------------------------------------------- /include/MotionPathManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // MotionPathManager.h 3 | // MotionPath 4 | // 5 | // Created by Daniele Federico on 09/11/14. 6 | // 7 | // 8 | 9 | #ifndef MOTIONPATHMANAGER_H 10 | #define MOTIONPATHMANAGER_H 11 | 12 | #include "MotionPathEditContext.h" 13 | #include "MotionPath.h" 14 | 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | #include 44 | #include 45 | 46 | struct RegisteredPanel 47 | { 48 | MString name; 49 | MCallbackId destroyPanelCallbackId; 50 | MCallbackId postRenderCallbackId; 51 | MCallbackId cameraWorldMatrixCallbackId; 52 | MCallbackId cameraChangedId; 53 | MCallbackId cameraNameChangedId; 54 | }; 55 | 56 | typedef std::vector RegisteredPanelArray; 57 | 58 | class MotionPathManager 59 | { 60 | public: 61 | MotionPathManager(); 62 | ~MotionPathManager(); 63 | 64 | void setupViewports(); 65 | void cleanupViewports(); 66 | void addCallbacks(); 67 | void removeCallbacks(); 68 | 69 | MStringArray getSelectionList(); 70 | void refreshDisplayTimeRange(); 71 | void setTimeRange(const double start, const double end); 72 | bool expandParentMatrixAndPivotCache(const double currentTimeValue); 73 | MotionPath* getMotionPathPtr(const int id); 74 | int getMotionPathsCount(){return pathArray.size();}; 75 | void drawCurvesForSelection(M3dView &view, CameraCache *cachePtr); 76 | 77 | void addBufferPaths(); 78 | void deleteAllBufferPaths(); 79 | void deleteBufferPathAtIndex(const int index); 80 | void setSelectStateForBufferPathAtIndex(const int index, const bool value); 81 | 82 | void startAnimUndoRecording(); 83 | MAnimCurveChange* getAnimCurveChangePtr(){return this->animCurveChangePtr;}; 84 | void startDGUndoRecording(); 85 | MDGModifier* getDGModifierPtr(){return this->dgModifierPtr;}; 86 | void stopDGAndAnimUndoRecording(); 87 | 88 | BufferPath* getBufferPathAtIndex(int index); 89 | 90 | void storePreviousKeySelection(); 91 | void getPreviousKeySelection(std::vector &sel); 92 | void getCurrentKeySelection(std::vector &sel); 93 | 94 | static void selectionChangeCallback(void *data); 95 | 96 | void clearParentMatrixCaches(); 97 | 98 | CameraCache *getCameraCachePtrFromView(M3dView &view); 99 | 100 | void refreshCameraCallbackForPanel(const MString &panelName, MDagPath &camera); 101 | void createCameraCacheForCamera(const MDagPath &camera); 102 | 103 | void cacheCameras(); 104 | 105 | void createMotionPathWorldCallback(); 106 | void destroyMotionPathWorldCallback(); 107 | 108 | void drawBufferPaths(M3dView &view, CameraCache* cachePtr, MHWRender::MUIDrawManager* drawManager = NULL, const MHWRender::MFrameContext* frameContext = NULL); 109 | void drawPaths(M3dView view, CameraCache* cachePtr, MHWRender::MUIDrawManager* drawManager = NULL, const MHWRender::MFrameContext* frameContext = NULL); 110 | 111 | //void destroyCameraCachesAndCameraCallbacks(); 112 | //void createCameraCachesAndCameraCallbacks(); 113 | 114 | private: 115 | bool cacheDone; 116 | MCallbackIdArray cbIDs; 117 | RegisteredPanelArray registeredPanels; 118 | MObjectArray selectionObjects; 119 | std::vector pathArray; 120 | std::vector bufferPathArray; 121 | MAnimCurveChange* animCurveChangePtr; 122 | MDGModifier *dgModifierPtr; 123 | CameraCacheMap cameraCache; 124 | 125 | std::vector previousKeySelection; 126 | 127 | int isMObjectContained(const MObject &obj, const MObjectArray &a); 128 | 129 | void getDagPath(const MString &name, MDagPath &dp); 130 | 131 | void getSelection(MObjectArray &objArray); 132 | void setSelectionList(const MObjectArray &list); 133 | 134 | bool hasSelectionListChanged(const MObjectArray &objArray); 135 | bool isContainedInMObjectArray(const MObjectArray &objArray, const MObject &obj); 136 | void highlightSelection(const MObjectArray &objArray); 137 | void setupViewport(const MString &panelName); 138 | 139 | static void timeChangeEvent(MTime ¤tTime, void* data); 140 | static void commandEvent(const MString &message, MCommandMessage::MessageType messageType, void *data); 141 | static void viewPostRenderCallback(const MString& panelName, void* data); 142 | static void viewDestroyCallback(const MString& panelName, void* data); 143 | static void autoKeyframeCallback(bool state, void* data); 144 | static void deleteAllCallback(void *data); 145 | static void sceneOpenedCallback(void *data); 146 | static void cameraWorldMatrixChangedCallback(MObject& transformNode, MDagMessage::MatrixModifiedFlags& modified,void* data); 147 | static void viewCameraChanged(const MString &str, MObject &node, void *data); 148 | static void viewCameraNameChanged(MObject &node, const MString &str, void *data); 149 | 150 | void removePanelCallback(const RegisteredPanel &panel); 151 | 152 | int panelRegistered(const MString &panelName); 153 | }; 154 | 155 | 156 | #endif 157 | -------------------------------------------------------------------------------- /include/MotionPathOverride.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define MOTION_PATH_RENDER_OVERRIDE_NAME "ToolchefsMotionPathOverride" 8 | 9 | 10 | class MotionPathUserOperation : public MHWRender::MHUDRender 11 | { 12 | public: 13 | MotionPathUserOperation(const MString &name); 14 | virtual ~MotionPathUserOperation(); 15 | 16 | virtual MStatus execute(const MHWRender::MDrawContext & drawContext); 17 | virtual bool hasUIDrawables() const; 18 | virtual void addUIDrawables( 19 | MHWRender::MUIDrawManager& drawManager, 20 | const MHWRender::MFrameContext& frameContext); 21 | 22 | void setPanelName(const MString & name) 23 | { 24 | mPanelName.set(name.asChar()); 25 | } 26 | 27 | 28 | private: 29 | MString mPanelName; 30 | }; 31 | 32 | 33 | 34 | class MotionPathRenderOverride : public MHWRender::MRenderOverride 35 | { 36 | public: 37 | // operation names 38 | static const MString kMotionPathPassName; 39 | 40 | MotionPathRenderOverride(const MString & name); 41 | virtual ~MotionPathRenderOverride(); 42 | virtual MHWRender::DrawAPI supportedDrawAPIs() const; 43 | 44 | // Basic setup and cleanup 45 | virtual MStatus setup(const MString & destination); 46 | virtual MStatus cleanup(); 47 | 48 | // UI name 49 | virtual MString uiName() const 50 | { 51 | return mUIName; 52 | } 53 | 54 | protected: 55 | 56 | // UI name 57 | MString mUIName; 58 | MString mPanelName; 59 | MotionPathUserOperation* mMotionPathOp; 60 | }; 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /include/Vp2DrawUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | namespace VP2DrawUtils 17 | { 18 | void drawLineStipple(const MVector &origin, const MVector &target, float lineWidth, const MColor &color, const MMatrix &cameraMatrix, MHWRender::MUIDrawManager* drawManager, const MHWRender::MFrameContext* frameContext); 19 | 20 | void drawLine(const MVector &origin, const MVector &target, float lineWidth, const MMatrix &cameraMatrix, MHWRender::MUIDrawManager* drawManager, const MHWRender::MFrameContext* frameContext); 21 | 22 | void drawLineWithColor(const MVector &origin, const MVector &target, float lineWidth, const MColor &color, const MMatrix &cameraMatrix, MHWRender::MUIDrawManager* drawManager, const MHWRender::MFrameContext* frameContext); 23 | 24 | void drawPoint(const MVector &point, float size, const MMatrix &cameraMatrix, MHWRender::MUIDrawManager* drawManager, const MHWRender::MFrameContext* frameContext); 25 | 26 | void drawPointWithColor(const MVector &point, float size, const MColor &color, const MMatrix &cameraMatrix, MHWRender::MUIDrawManager* drawManager, const MHWRender::MFrameContext* frameContext); 27 | 28 | void drawKeyFramePoints(KeyframeMap &keyframesCache, const float size, const double colorMultiplier, const int portWidth, const int portHeight, const bool showRotationKeyframes, const MMatrix &cameraMatrix, MHWRender::MUIDrawManager* drawManager, const MHWRender::MFrameContext* frameContext); 29 | 30 | void drawKeyFrames(std::vector keys, const float size, const double colorMultiplier, const int portWidth, const int portHeight, const bool showRotationKeyframes, const MMatrix &cameraMatrix, MHWRender::MUIDrawManager* drawManager, const MHWRender::MFrameContext* frameContext); 31 | 32 | void convertWorldSpaceToCameraSpace(CameraCache* cachePtr, std::map &positions, std::map &screenSpacePositions, MHWRender::MUIDrawManager* drawManager, const MHWRender::MFrameContext* frameContext); 33 | 34 | void drawFrameLabel(double frame, const MVector &framePos, M3dView &view, const double sizeOffset, const MColor &color, const MMatrix &cameraMatrix, MHWRender::MUIDrawManager* drawManager, const MHWRender::MFrameContext* frameContext); 35 | } -------------------------------------------------------------------------------- /include/animCurveUtils.h: -------------------------------------------------------------------------------- 1 | // 2 | // animCurveUtils.h 3 | // MotionPath 4 | // 5 | // Created by Daniele Federico on 15/06/15. 6 | // 7 | // 8 | 9 | #ifndef __MotionPath__animCurveUtils__ 10 | #define __MotionPath__animCurveUtils__ 11 | 12 | #include 13 | #include 14 | 15 | namespace animCurveUtils 16 | { 17 | 18 | void restoreCurve(MFnAnimCurve &curve, const MTime ¤tTime, const double oldValue, const int newKeyId, const int oldKeyId); 19 | 20 | bool updateCurve(const MPlug &plug, MFnAnimCurve &curve, const MTime ¤tTime, double &oldValue, double &newValue, int &newKeyId, int &oldKeyId); 21 | 22 | } 23 | 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /python/tcMotionPath/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Toolchefs/motionPath/1d02754694edddeca4f09ba057e2d92cc51674e1/python/tcMotionPath/__init__.py -------------------------------------------------------------------------------- /python/tcMotionPath/icons/abouts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Toolchefs/motionPath/1d02754694edddeca4f09ba057e2d92cc51674e1/python/tcMotionPath/icons/abouts.png -------------------------------------------------------------------------------- /python/tcMotionPath/icons/motionPathDraw.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Toolchefs/motionPath/1d02754694edddeca4f09ba057e2d92cc51674e1/python/tcMotionPath/icons/motionPathDraw.png -------------------------------------------------------------------------------- /python/tcMotionPath/icons/motionPathEdit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Toolchefs/motionPath/1d02754694edddeca4f09ba057e2d92cc51674e1/python/tcMotionPath/icons/motionPathEdit.png -------------------------------------------------------------------------------- /source/BufferPath.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // BufferPath.cpp 3 | // MotionPath 4 | // 5 | // Created by Daniele Federico on 06/12/14. 6 | // 7 | // 8 | 9 | #include "BufferPath.h" 10 | #include "GlobalSettings.h" 11 | #include "DrawUtils.h" 12 | #include "Vp2DrawUtils.h" 13 | 14 | BufferPath::BufferPath() 15 | { 16 | black = MColor(0,0,0); 17 | selected = false; 18 | } 19 | 20 | void BufferPath::drawFrames(const double startTime, const double endTime, const MColor &curveColor, CameraCache* cachePtr, const MMatrix ¤tCameraMatrix, M3dView &view, MHWRender::MUIDrawManager* drawManager, const MHWRender::MFrameContext* frameContext) 21 | { 22 | int frameSize = frames.size(); 23 | 24 | if (GlobalSettings::motionPathDrawMode == GlobalSettings::kCameraSpace) 25 | cachePtr->ensureMatricesAtTime(startTime); 26 | 27 | for(double i = startTime + 1; i <= endTime; i += 1.0) 28 | { 29 | if (i <= minTime || i >= minTime + frameSize) 30 | continue; 31 | 32 | int index = static_cast(i - minTime); 33 | 34 | MVector pos1 = frames[index]; 35 | MVector pos2 = frames[index-1]; 36 | if (GlobalSettings::motionPathDrawMode == GlobalSettings::kCameraSpace) 37 | { 38 | cachePtr->ensureMatricesAtTime(i); 39 | pos1 = MPoint(pos1) * cachePtr->matrixCache[i] * currentCameraMatrix; 40 | pos2 = MPoint(pos2) * cachePtr->matrixCache[i-1] * currentCameraMatrix; 41 | } 42 | 43 | if (GlobalSettings::showPath) 44 | { 45 | if (drawManager) 46 | VP2DrawUtils::drawLineWithColor(pos1, pos2, GlobalSettings::pathSize, curveColor, currentCameraMatrix, drawManager, frameContext); 47 | else 48 | drawUtils::drawLineWithColor(pos1, pos2, GlobalSettings::pathSize, curveColor); 49 | } 50 | 51 | if (drawManager) 52 | VP2DrawUtils::drawPointWithColor(pos2, GlobalSettings::frameSize, curveColor, currentCameraMatrix, drawManager, frameContext); 53 | else 54 | drawUtils::drawPointWithColor(pos2, GlobalSettings::frameSize, curveColor); 55 | 56 | if (i == endTime || i == minTime + frameSize - 1) 57 | { 58 | if (drawManager) 59 | VP2DrawUtils::drawPointWithColor(pos1, GlobalSettings::frameSize, curveColor, currentCameraMatrix, drawManager, frameContext); 60 | else 61 | drawUtils::drawPointWithColor(pos1, GlobalSettings::frameSize, curveColor); 62 | } 63 | } 64 | } 65 | 66 | void BufferPath::drawKeyFrames(const double startTime, const double endTime, const MColor &curveColor, CameraCache* cachePtr, const MMatrix ¤tCameraMatrix, M3dView &view, MHWRender::MUIDrawManager* drawManager, const MHWRender::MFrameContext* frameContext) 67 | { 68 | for(BPKeyframeIterator keyIt = keyFrames.begin(); keyIt != keyFrames.end(); ++keyIt) 69 | { 70 | double time = keyIt->first; 71 | if (time >= startTime && time <= endTime) 72 | { 73 | MVector pos = keyIt->second; 74 | if (GlobalSettings::motionPathDrawMode == GlobalSettings::kCameraSpace) 75 | { 76 | cachePtr->ensureMatricesAtTime(time); 77 | pos = MPoint(pos) * cachePtr->matrixCache[time] * currentCameraMatrix; 78 | } 79 | 80 | if (drawManager) 81 | VP2DrawUtils::drawPointWithColor(pos, GlobalSettings::frameSize, curveColor, GlobalSettings::cameraMatrix, drawManager, frameContext); 82 | else 83 | drawUtils::drawPointWithColor(pos, GlobalSettings::frameSize * 1.5, curveColor); 84 | } 85 | } 86 | } 87 | 88 | void BufferPath::draw(M3dView &view, CameraCache* cachePtr, MHWRender::MUIDrawManager* drawManager, const MHWRender::MFrameContext* frameContext) 89 | { 90 | MColor curveColor = GlobalSettings::bufferPathColor; 91 | 92 | if(selected) 93 | { 94 | curveColor.r = 1.0 - curveColor.r; 95 | curveColor.g = 1.0 - curveColor.g; 96 | curveColor.b = 1.0 - curveColor.b; 97 | } 98 | 99 | curveColor.a = 0.5; 100 | 101 | double currentTime = MAnimControl::currentTime().as(MTime::uiUnit()); 102 | 103 | double startTime = currentTime - GlobalSettings::framesBack; 104 | double endTime = currentTime + GlobalSettings::framesFront; 105 | 106 | MMatrix currentCameraMatrix; 107 | if (GlobalSettings::motionPathDrawMode == GlobalSettings::kCameraSpace) 108 | { 109 | double currentTime = MAnimControl::currentTime().as(MTime::uiUnit()); 110 | cachePtr->ensureMatricesAtTime(currentTime); 111 | currentCameraMatrix = cachePtr->matrixCache[currentTime].inverse(); 112 | } 113 | 114 | drawFrames(startTime, endTime, curveColor, cachePtr, GlobalSettings::cameraMatrix, view, drawManager, frameContext); 115 | if (GlobalSettings::showKeyFrames) 116 | drawKeyFrames(startTime, endTime, curveColor, cachePtr, GlobalSettings::cameraMatrix, view, drawManager, frameContext); 117 | 118 | //draw current frame 119 | if (currentTime >= minTime && currentTime <= minTime + frames.size()) 120 | { 121 | MColor currentColor = GlobalSettings::currentFrameColor * 0.8; 122 | currentColor.a = 0.7; 123 | 124 | int numFrame = static_cast(currentTime) - static_cast(minTime); 125 | if (numFrame < 0 || numFrame > frames.size() - 1) 126 | return; 127 | 128 | MVector pos = frames[static_cast(currentTime) - static_cast(minTime)]; 129 | if (GlobalSettings::motionPathDrawMode == GlobalSettings::kCameraSpace) 130 | { 131 | cachePtr->ensureMatricesAtTime(currentTime); 132 | pos = MPoint(pos) * cachePtr->matrixCache[currentTime] * currentCameraMatrix; 133 | } 134 | 135 | if (drawManager) 136 | VP2DrawUtils::drawPointWithColor(pos, GlobalSettings::frameSize, curveColor, GlobalSettings::cameraMatrix, drawManager, frameContext); 137 | else 138 | drawUtils::drawPointWithColor(pos, GlobalSettings::frameSize * 1.6, currentColor); 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /source/CameraCache.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // CameraCache.cpp 3 | // MotionPath 4 | // 5 | // Created by Daniele Federico on 11/05/15. 6 | // 7 | // 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "CameraCache.h" 15 | #include "GlobalSettings.h" 16 | #include "animCurveUtils.h" 17 | 18 | 19 | 20 | CameraCache::CameraCache() 21 | { 22 | caching = false; 23 | initialized = false; 24 | } 25 | 26 | void CameraCache::initialize(const MObject &camera) 27 | { 28 | MFnDependencyNode fnCamera(camera); 29 | MPlug worldMatrixPlugs = fnCamera.findPlug("worldMatrix"); 30 | worldMatrixPlugs.evaluateNumElements(); 31 | worldMatrixPlug = worldMatrixPlugs[0]; 32 | 33 | caching = false; 34 | initialized = true; 35 | 36 | MDagPath dagPath; 37 | MDagPath::getAPathTo(camera, dagPath); 38 | dagPath.pop(1); 39 | 40 | MFnDependencyNode transformFn(dagPath.node()); 41 | txPlug = transformFn.findPlug("translateX"); 42 | tyPlug = transformFn.findPlug("translateY"); 43 | tzPlug = transformFn.findPlug("translateZ"); 44 | 45 | rxPlug = transformFn.findPlug("rotateX"); 46 | ryPlug = transformFn.findPlug("rotateY"); 47 | rzPlug = transformFn.findPlug("rotateZ"); 48 | } 49 | 50 | 51 | void CameraCache::cacheCamera() 52 | { 53 | double currentFrame = MAnimControl::currentTime().as(MTime::uiUnit()); 54 | 55 | double startFrame = currentFrame - GlobalSettings::framesBack; 56 | double endFrame = currentFrame + GlobalSettings::framesFront; 57 | 58 | if(startFrame < GlobalSettings::startTime) startFrame = GlobalSettings::startTime; 59 | if(endFrame > GlobalSettings::endTime) endFrame = GlobalSettings::endTime; 60 | 61 | if (worldMatrixPlug.isNull()) 62 | return; 63 | 64 | caching = true; 65 | 66 | MTime currentTime = MAnimControl::currentTime(); 67 | 68 | MStatus xStatus, yStatus, zStatus, rotxStatus, rotyStatus, rotzStatus; 69 | MFnAnimCurve curveX(txPlug, &xStatus); 70 | MFnAnimCurve curveY(tyPlug, &yStatus); 71 | MFnAnimCurve curveZ(tzPlug, &zStatus); 72 | MFnAnimCurve curveRotX(rxPlug, &rotxStatus); 73 | MFnAnimCurve curveRotY(ryPlug, &rotyStatus); 74 | MFnAnimCurve curveRotZ(rzPlug, &rotzStatus); 75 | 76 | double newXValue, newYValue, newZValue, newRotXValue, newRotYValue, newRotZValue; 77 | double oldXValue, oldYValue, oldZValue, oldRotXValue, oldRotYValue, oldRotZValue; 78 | int newKeyX, newKeyY, newKeyZ, newKeyRotX, newKeyRotY, newKeyRotZ; 79 | int oldKeyX, oldKeyY, oldKeyZ, oldKeyRotX, oldKeyRotY, oldKeyRotZ; 80 | bool xUpdated = (xStatus == MS::kSuccess), yUpdated = (yStatus == MS::kSuccess), zUpdated = (zStatus == MS::kSuccess); 81 | bool rotxUpdated = (rotxStatus == MS::kSuccess), rotyUpdated = (rotyStatus == MS::kSuccess), rotzUpdated = (rotzStatus == MS::kSuccess); 82 | if (xStatus != MS::kNotFound) 83 | xUpdated = animCurveUtils::updateCurve(txPlug, curveX, currentTime, oldXValue, newXValue, newKeyX, oldKeyX); 84 | if (yStatus != MS::kNotFound) 85 | yUpdated = animCurveUtils::updateCurve(tyPlug, curveY, currentTime, oldYValue, newYValue, newKeyY, oldKeyY); 86 | if (zStatus != MS::kNotFound) 87 | zUpdated = animCurveUtils::updateCurve(tzPlug, curveZ, currentTime, oldZValue, newZValue, newKeyZ, oldKeyZ); 88 | if (rotxStatus != MS::kNotFound) 89 | rotxUpdated = animCurveUtils::updateCurve(rxPlug, curveRotX, currentTime, oldRotXValue, newRotXValue, newKeyRotX, oldKeyRotX); 90 | if (rotyStatus != MS::kNotFound) 91 | rotyUpdated = animCurveUtils::updateCurve(ryPlug, curveRotY, currentTime, oldRotYValue, newRotYValue, newKeyRotY, oldKeyRotY); 92 | if (rotzStatus != MS::kNotFound) 93 | rotzUpdated = animCurveUtils::updateCurve(rzPlug, curveRotZ, currentTime, oldRotZValue, newRotZValue, newKeyRotZ, oldKeyRotZ); 94 | 95 | matrixCache.clear(); 96 | 97 | for (double i = startFrame; i <= endFrame; ++i) 98 | { 99 | MTime evalTime(i, MTime::uiUnit()); 100 | MDGContext context(evalTime); 101 | 102 | MObject val; 103 | worldMatrixPlug.getValue(val, context); 104 | matrixCache[i] = MFnMatrixData(val).matrix().inverse(); 105 | } 106 | 107 | //restoring the previous values if a keyframe was not actually set by the user 108 | if (xUpdated && xStatus != MS::kNotFound) 109 | { 110 | animCurveUtils::restoreCurve(curveX, currentTime, oldXValue, newKeyX, oldKeyX); 111 | txPlug.setValue(newXValue); 112 | } 113 | if (yUpdated && yStatus != MS::kNotFound) 114 | { 115 | animCurveUtils::restoreCurve(curveY, currentTime, oldYValue, newKeyY, oldKeyY); 116 | tyPlug.setValue(newYValue); 117 | } 118 | if (zUpdated && zStatus != MS::kNotFound ) 119 | { 120 | animCurveUtils::restoreCurve(curveZ, currentTime, oldZValue, newKeyZ, oldKeyZ); 121 | tzPlug.setValue(newZValue); 122 | } 123 | 124 | if (rotxUpdated && rotxStatus != MS::kNotFound) 125 | { 126 | animCurveUtils::restoreCurve(curveRotX, currentTime, oldRotXValue, newKeyRotX, oldKeyRotX); 127 | rxPlug.setValue(newRotXValue); 128 | } 129 | if (rotyUpdated && rotyStatus != MS::kNotFound) 130 | { 131 | animCurveUtils::restoreCurve(curveRotY, currentTime, oldRotYValue, newKeyRotY, oldKeyRotY); 132 | ryPlug.setValue(newRotYValue); 133 | } 134 | if (rotzUpdated && rotzStatus != MS::kNotFound ) 135 | { 136 | animCurveUtils::restoreCurve(curveRotZ, currentTime, oldRotZValue, newKeyRotZ, oldKeyRotZ); 137 | rzPlug.setValue(newRotZValue); 138 | } 139 | 140 | caching = false; 141 | } 142 | 143 | void CameraCache::checkRangeIsCached() 144 | { 145 | double currentFrame = MAnimControl::currentTime().as(MTime::uiUnit()); 146 | 147 | double startFrame = currentFrame - GlobalSettings::framesBack; 148 | double endFrame = currentFrame + GlobalSettings::framesFront; 149 | 150 | if(startFrame < GlobalSettings::startTime) startFrame = GlobalSettings::startTime; 151 | if(endFrame > GlobalSettings::endTime) endFrame = GlobalSettings::endTime; 152 | 153 | if (worldMatrixPlug.isNull()) 154 | return; 155 | 156 | caching = true; 157 | 158 | for (double i = startFrame; i <= endFrame; ++i) 159 | { 160 | if (matrixCache.find(i) == matrixCache.end()) 161 | { 162 | MTime evalTime(i, MTime::uiUnit()); 163 | MDGContext context(evalTime); 164 | 165 | MObject val; 166 | worldMatrixPlug.getValue(val, context); 167 | matrixCache[i] = MFnMatrixData(val).matrix().inverse(); 168 | } 169 | } 170 | caching = false; 171 | } 172 | 173 | void CameraCache::ensureMatricesAtTime(const double time, const bool force) 174 | { 175 | if (matrixCache.find(time) == matrixCache.end() || force) 176 | { 177 | if (worldMatrixPlug.isNull()) 178 | return; 179 | 180 | std::string name = worldMatrixPlug.name().asChar(); 181 | 182 | MTime evalTime(time, MTime::uiUnit()); 183 | 184 | MDGContext context(evalTime); 185 | 186 | MObject val; 187 | worldMatrixPlug.getValue(val, context); 188 | matrixCache[time] = MFnMatrixData(val).matrix().inverse(); 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /source/ContextUtils.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // ContextUtils.cpp 3 | // MotionPath 4 | // 5 | // Created by Daniele Federico on 29/11/14. 6 | // 7 | // 8 | 9 | #include "ContextUtils.h" 10 | #include "Keyframe.h" 11 | 12 | #include 13 | #include 14 | 15 | bool contextUtils::worldCameraSpaceToWorldSpace(MVector &position, M3dView &view, const double time, const MMatrix &inverseCameraMatrix, MotionPathManager &mpManager) 16 | { 17 | CameraCache * cachePtr = mpManager.getCameraCachePtrFromView(view); 18 | if (!cachePtr) 19 | return false; 20 | cachePtr->ensureMatricesAtTime(time); 21 | position = position * inverseCameraMatrix * cachePtr->matrixCache[time].inverse(); 22 | return true; 23 | } 24 | 25 | bool contextUtils::worldCameraSpaceToWorldSpace(MPoint &position, M3dView &view, const double time, const MMatrix &inverseCameraMatrix, MotionPathManager &mpManager) 26 | { 27 | CameraCache * cachePtr = mpManager.getCameraCachePtrFromView(view); 28 | if (!cachePtr) 29 | return false; 30 | cachePtr->ensureMatricesAtTime(time); 31 | position = position * inverseCameraMatrix * cachePtr->matrixCache[time].inverse(); 32 | return true; 33 | } 34 | 35 | MVector contextUtils::getWorldPositionFromProjPoint(const MVector &pointToMove, const double initialX, const double initialY, const double currentX, const double currentY, const M3dView &view, const MVector &cameraPosition) 36 | { 37 | MPoint startPoint, endPoint; 38 | MVector worldVectorStart, worldVectorEnd; 39 | 40 | view.viewToWorld(initialX, initialY, startPoint, worldVectorStart); 41 | view.viewToWorld(currentX, currentY, endPoint, worldVectorEnd); 42 | 43 | double distanceToCamera = (pointToMove - cameraPosition).length(); 44 | 45 | startPoint += worldVectorStart * distanceToCamera; 46 | endPoint += worldVectorEnd * distanceToCamera; 47 | 48 | return (endPoint - startPoint) + pointToMove; 49 | } 50 | 51 | int contextUtils::processCurveHits(M3dView &view, CameraCache *cachePtr, MotionPathManager &mpManager) 52 | { 53 | GLuint glSelectionBuffer[256]; 54 | view.beginSelect(glSelectionBuffer, 256); 55 | view.initNames(); 56 | 57 | mpManager.drawCurvesForSelection(view, cachePtr); 58 | 59 | GLint hits = view.endSelect(); 60 | if (hits == 0) return -1; 61 | 62 | GLuint* ptr = (GLuint *) glSelectionBuffer; 63 | ptr += (hits - 1) * 4 + 3; 64 | return *ptr; 65 | } 66 | 67 | int contextUtils::processCurveHits(const short mx, const short my, const MMatrix &cameraMatrix, M3dView &view, CameraCache *cachePtr, MotionPathManager &mpManager) 68 | { 69 | for (unsigned int i = 0; i < mpManager.getMotionPathsCount(); ++i) 70 | { 71 | MotionPath* mpPtr = mpManager.getMotionPathPtr(i); 72 | if (!mpPtr) 73 | continue; 74 | 75 | std::vector> vec; 76 | 77 | MIntArray keys; 78 | contextUtils::processKeyFrameHits(mx, my, mpPtr, view, cameraMatrix, cachePtr, keys); 79 | if (keys.length() > 0) 80 | return i; 81 | 82 | int selectedKeyId, selectedTangent; 83 | contextUtils::processTangentHits(mx, my, mpPtr, view, cameraMatrix, cachePtr, selectedKeyId, selectedTangent); 84 | if (selectedTangent != -1) 85 | return i; 86 | 87 | double time; 88 | if (contextUtils::processFramesHits(mx, my, mpPtr, view, cameraMatrix, cachePtr, time)) 89 | return i; 90 | } 91 | return -1; 92 | } 93 | 94 | void contextUtils::processKeyFrameHits(const short mx, const short my, MotionPath* motionPathPtr, M3dView &view, const MMatrix &cameraMatrix, CameraCache *cachePtr, MIntArray &selectedKeys) 95 | { 96 | KeyframeMap *km = motionPathPtr->keyFramesCachePtr(); 97 | int key = -1; 98 | 99 | double kfs = GlobalSettings::frameSize * 1.5 / 2; 100 | kfs = kfs * kfs; 101 | for (KeyframeMapIterator it = km->begin(); it != km->end(); ++it) 102 | { 103 | Keyframe &k = it->second; 104 | short x, y; 105 | view.worldToView(k.worldPosition, x, y); 106 | 107 | double distance = (mx - x) * (mx - x) + (my - y) * (my - y); 108 | if (distance < kfs) 109 | key = it->second.id; 110 | } 111 | 112 | if (key != -1) 113 | selectedKeys.append(key); 114 | } 115 | 116 | void contextUtils::processTangentHits(const short mx, const short my, MotionPath* motionPathPtr, M3dView &view, const MMatrix &cameraMatrix, CameraCache *cachePtr, int &selectedKeyId, int &selectedTangent) 117 | { 118 | KeyframeMap *km = motionPathPtr->keyFramesCachePtr(); 119 | 120 | double tfs = GlobalSettings::frameSize / 2; 121 | tfs = tfs * tfs; 122 | 123 | selectedTangent = -1; 124 | 125 | for (KeyframeMapIterator it = km->begin(); it != km->end(); ++it) 126 | { 127 | Keyframe &k = it->second; 128 | short x, y; 129 | view.worldToView(k.inTangentWorldFromCurve, x, y); 130 | 131 | double distance = (mx - x) * (mx - x) + (my - y) * (my - y); 132 | if (distance < tfs) 133 | { 134 | selectedKeyId = k.id; 135 | selectedTangent = (int)Keyframe::kInTangent; 136 | return; 137 | } 138 | 139 | view.worldToView(k.outTangentWorldFromCurve, x, y); 140 | distance = (mx - x) * (mx - x) + (my - y) * (my - y); 141 | if (distance < tfs) 142 | { 143 | selectedKeyId = k.id; 144 | selectedTangent = (int)Keyframe::kOutTangent; 145 | return; 146 | } 147 | } 148 | } 149 | 150 | bool contextUtils::processFramesHits(const short mx, const short my, MotionPath* motionPathPtr, M3dView &view, const MMatrix &cameraMatrix, CameraCache *cachePtr, double &time) 151 | { 152 | double fs = GlobalSettings::frameSize / 2; 153 | fs = fs * fs; 154 | 155 | std::vector> vec; 156 | motionPathPtr->getFramePositions(vec); 157 | for (unsigned int i = 0; i < vec.size(); ++i) 158 | { 159 | MVector& pos = vec[i].second; 160 | 161 | short x, y; 162 | view.worldToView(MPoint(pos.x, pos.y, pos.z), x, y); 163 | 164 | double distance = (mx - x) * (mx - x) + (my - y) * (my - y); 165 | if (distance < fs) 166 | { 167 | time = vec[i].first; 168 | return true; 169 | } 170 | } 171 | 172 | return false; 173 | } 174 | 175 | void contextUtils::processTangentHits(MotionPath* motionPathPtr, M3dView &view, CameraCache *cachePtr, int &selectedKeyId, int &selectedTangent) 176 | { 177 | GLuint glSelectionBuffer[256]; 178 | GLint hits; 179 | 180 | view.beginSelect(glSelectionBuffer, 256); 181 | view.initNames(); 182 | motionPathPtr->drawTangentsForSelection(view, cachePtr); 183 | 184 | hits = view.endSelect(); 185 | 186 | if (hits == 0) 187 | { 188 | selectedTangent = -1; 189 | return; 190 | } 191 | 192 | GLuint* ptr = (GLuint *) glSelectionBuffer; 193 | ptr += (hits - 1) * 5 + 3; 194 | selectedKeyId = *ptr; 195 | ++ptr; 196 | selectedTangent = *ptr; 197 | } 198 | 199 | void contextUtils::processKeyFrameHits(MotionPath* motionPathPtr, M3dView &view, CameraCache *cachePtr, MIntArray &selectedKeys) 200 | { 201 | GLuint glSelectionBuffer[256]; 202 | GLint hits; 203 | 204 | view.beginSelect(glSelectionBuffer, 256); 205 | view.initNames(); 206 | motionPathPtr->drawKeysForSelection(view, cachePtr); 207 | hits = view.endSelect(); 208 | 209 | if (hits == 0) 210 | return; 211 | 212 | GLuint* ptr = (GLuint *) glSelectionBuffer; 213 | ptr += (hits - 1) * 4 + 1; 214 | GLuint minZ = *ptr; 215 | ptr += 2; 216 | selectedKeys.append(*ptr); 217 | 218 | for (int i = 0; i < hits - 1; ++i) 219 | { 220 | if (minZ == glSelectionBuffer[i * 4 + 1]) 221 | selectedKeys.append(glSelectionBuffer[i * 4 + 3]); 222 | } 223 | } 224 | 225 | bool contextUtils::processFramesHits(MotionPath* motionPathPtr, M3dView &view, CameraCache *cachePtr, double &time) 226 | { 227 | GLuint glSelectionBuffer[256]; 228 | GLint hits; 229 | 230 | view.beginSelect(glSelectionBuffer, 256); 231 | view.initNames(); 232 | motionPathPtr->drawFramesForSelection(view, cachePtr); 233 | 234 | hits = view.endSelect(); 235 | 236 | if (hits == 0) 237 | return false; 238 | 239 | GLuint* ptr = (GLuint *) glSelectionBuffer; 240 | ptr += (hits - 1) * 4 + 3; 241 | time = *ptr; 242 | return true; 243 | } 244 | 245 | void contextUtils::drawMarqueeGL(short initialX, short initialY, short finalX, short finalY) 246 | { 247 | glBegin( GL_LINE_LOOP ); 248 | glVertex2i( initialX, initialY ); 249 | glVertex2i( finalX, initialY ); 250 | glVertex2i( finalX, finalY ); 251 | glVertex2i( initialX, finalY ); 252 | glEnd(); 253 | } 254 | 255 | void contextUtils::drawMarquee(MHWRender::MUIDrawManager& drawMgr, short initialX, short initialY, short finalX, short finalY) 256 | { 257 | drawMgr.beginDrawable(); 258 | 259 | drawMgr.line2d( MPoint( initialX, initialY), MPoint(finalX, initialY) ); 260 | drawMgr.line2d( MPoint( finalX, initialY), MPoint(finalX, finalY) ); 261 | drawMgr.line2d( MPoint( finalX, finalY), MPoint(initialX, finalY) ); 262 | drawMgr.line2d( MPoint( initialX, finalY), MPoint(initialX, initialY) ); 263 | 264 | drawMgr.endDrawable(); 265 | } 266 | 267 | 268 | void contextUtils::applySelection(short initialX, short initialY, short finalX, short finalY, const MGlobal::ListAdjustment &listAdjustment) 269 | { 270 | MSelectionList incomingList, marqueeList; 271 | 272 | // Save the state of the current selections. The "selectFromSceen" 273 | // below will alter the active list, and we have to be able to put 274 | // it back. 275 | MGlobal::getActiveSelectionList(incomingList); 276 | 277 | // If we have a zero dimension box, just do a point pick 278 | // 279 | if ( abs(initialX - finalX) < 2 && abs(initialY - finalY) < 2 ) { 280 | // This will check to see if the active view is in wireframe or not. 281 | MGlobal::SelectionMethod selectionMethod = MGlobal::selectionMethod(); 282 | MGlobal::selectFromScreen( initialX, initialY, listAdjustment, selectionMethod ); 283 | } else { 284 | // The Maya select tool goes to wireframe select when doing a marquee, so 285 | // we will copy that behaviour. 286 | // Select all the objects or components within the marquee. 287 | MGlobal::selectFromScreen( initialX, initialY, finalX, finalY, 288 | listAdjustment, 289 | MGlobal::kWireframeSelectMethod ); 290 | } 291 | 292 | // Get the list of selected items 293 | MGlobal::getActiveSelectionList(marqueeList); 294 | 295 | //we need to set back the previous selection here or the undo for the tcMotionPathCmd won't work 296 | MGlobal::setActiveSelectionList(incomingList); 297 | 298 | //building args and running cmd 299 | MString cmd("tcMotionPathCmd -selectionChanged "); 300 | for (int i = 0; i < marqueeList.length(); ++i) 301 | { 302 | MDagPath d; 303 | marqueeList.getDagPath(i, d); 304 | if (d.isValid()) 305 | cmd += d.fullPathName() + " "; 306 | } 307 | MGlobal::executeCommand(cmd, true, true); 308 | } 309 | 310 | void contextUtils::refreshSelectionMethod(MEvent &event, MGlobal::ListAdjustment &listAdjustment) 311 | { 312 | if (event.isModifierShift() || event.isModifierControl() ) { 313 | if ( event.isModifierShift() ) { 314 | if ( event.isModifierControl() ) { 315 | // both shift and control pressed, merge new selections 316 | listAdjustment = MGlobal::kAddToList; 317 | } 318 | else 319 | { 320 | // shift only, xor new selections with previous ones 321 | listAdjustment = MGlobal::kXORWithList; 322 | } 323 | } 324 | else if ( event.isModifierControl() ) { 325 | // control only, remove new selections from the previous list 326 | listAdjustment = MGlobal::kRemoveFromList; 327 | } 328 | } 329 | else 330 | listAdjustment = MGlobal::kReplaceList; 331 | } 332 | 333 | 334 | -------------------------------------------------------------------------------- /source/DrawUtils.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // DrawUtils.cpp 3 | // MotionPath 4 | // 5 | // Created by Daniele Federico on 16/11/14. 6 | // 7 | // 8 | 9 | #include "DrawUtils.h" 10 | 11 | #define PI 3.1415 12 | 13 | void drawUtils::drawLineStipple(const MVector &origin, const MVector &target, float lineWidth, const MColor &color) 14 | { 15 | glEnable(GL_BLEND); 16 | glColor4d(color.r, color.g, color.b, color.a); 17 | 18 | float prevLineWidth; 19 | glGetFloatv(GL_LINE_WIDTH, &prevLineWidth); 20 | 21 | glLineWidth(lineWidth); 22 | 23 | glEnable(GL_LINE_STIPPLE); 24 | glLineStipple(8, 0xAAAA); 25 | 26 | glBegin(GL_LINES); 27 | glVertex3f(origin.x, origin.y, origin.z); 28 | glVertex3f(target.x, target.y, target.z); 29 | glEnd(); 30 | 31 | glDisable(GL_LINE_STIPPLE); 32 | 33 | glLineWidth(prevLineWidth); 34 | } 35 | 36 | 37 | void drawUtils::drawLine(const MVector &origin, const MVector &target, float lineWidth) 38 | { 39 | float prevLineWidth; 40 | glGetFloatv(GL_LINE_WIDTH, &prevLineWidth); 41 | 42 | glLineWidth(lineWidth); 43 | 44 | glBegin(GL_LINES); 45 | glVertex3f(origin.x, origin.y, origin.z); 46 | glVertex3f(target.x, target.y, target.z); 47 | glEnd(); 48 | 49 | glLineWidth(prevLineWidth);//important, as maya won't restore its width automatically 50 | } 51 | 52 | 53 | void drawUtils::drawLineWithColor(const MVector &origin, const MVector &target, float lineWidth, const MColor &color) 54 | { 55 | glEnable(GL_BLEND); 56 | glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 57 | glColor4d(color.r, color.g, color.b, color.a); 58 | 59 | drawUtils::drawLine(origin, target, lineWidth); 60 | } 61 | 62 | 63 | void drawUtils::drawPoint(const MVector &point, float size) 64 | { 65 | // if keyframe is only on one axis then use GL_POINT 66 | float prevSize; 67 | glGetFloatv(GL_POINT_SIZE, &prevSize); 68 | 69 | glPointSize(size); 70 | glEnable(GL_POINT_SMOOTH); 71 | 72 | glBegin(GL_POINTS); 73 | glVertex3f(point.x, point.y, point.z); 74 | glEnd(); 75 | 76 | glPointSize(prevSize); 77 | } 78 | 79 | 80 | void drawUtils::drawPointWithColor(const MVector &point, float size, const MColor &color) 81 | { 82 | glEnable(GL_BLEND); 83 | glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 84 | glColor4d(color.r, color.g, color.b, color.a); 85 | 86 | drawUtils::drawPoint(point, size); 87 | } 88 | 89 | void drawUtils::drawKeyFrames(std::vector keys, const float size, const double colorMultiplier,const int portWidth, const int portHeight, const bool showRotationKeyframes) 90 | { 91 | glMatrixMode(GL_MODELVIEW); //combinazione matrici model e inversa camera 92 | glPushMatrix(); 93 | glMatrixMode(GL_PROJECTION); 94 | glPushMatrix(); 95 | 96 | glMatrixMode(GL_PROJECTION); 97 | glLoadIdentity(); 98 | glOrtho(0.0, portWidth, portHeight, 0, 1, -1); 99 | 100 | glMatrixMode(GL_MODELVIEW); 101 | glLoadIdentity(); 102 | 103 | for(unsigned int ki = 0; ki < keys.size(); ++ki) 104 | { 105 | Keyframe* key = keys[ki]; 106 | if (!key) 107 | continue; 108 | 109 | if (key->projPosition.z > 1 || key->projPosition.z < 0) 110 | continue; 111 | 112 | std::vector tAxis, rAxis; 113 | key->getKeyTranslateAxis(tAxis); 114 | //std::cout << key->time << std::endl; 115 | if (tAxis.size() < 1) 116 | { 117 | //std::cout << "axis 0 " << key->time << std::endl; 118 | continue; 119 | } 120 | if (showRotationKeyframes) 121 | key->getKeyRotateAxis(rAxis); 122 | 123 | //converti winY in modo tale che l'origine non sia in alto a sinistra, ma in basso sinistra 124 | double convertY = portHeight - key->projPosition.y; 125 | double blackBackgroundFactor = 1.2; 126 | MColor color(0.0, 0.0, 0.0); 127 | drawPointWithColor(MVector(key->projPosition.x, convertY, 0.0f), size*blackBackgroundFactor, color); 128 | 129 | if (key->selectedFromTool) 130 | { 131 | MColor color(1.0, 1.0, 1.0); 132 | drawPointWithColor(MVector(key->projPosition.x, convertY, 0.0f), size, color); 133 | } 134 | else 135 | { 136 | //std::cout << "begin triangle" << std::endl; 137 | glBegin(GL_TRIANGLES); 138 | 139 | int nSections = 12; 140 | int step = nSections / tAxis.size(); 141 | int currentStep = 0; 142 | //std::cout << "triangle 1" << std::endl; 143 | Keyframe::getColorForAxis(tAxis[currentStep], color); 144 | color *= colorMultiplier; 145 | glColor4d(color.r, color.g, color.b, color.a); 146 | //std::cout << "triangle 2" << std::endl; 147 | double angleAdd = (2.0 * double(PI) / double(nSections)); 148 | double angle = -PI / 2; 149 | GLfloat x = 0; 150 | GLfloat y = size/2; 151 | //std::cout << "init section" << std::endl; 152 | for (int i = 0; i <= nSections; ++i) 153 | { 154 | //std::cout << i << std::endl; 155 | if (i / step > currentStep) 156 | { 157 | currentStep = i / step; 158 | if (currentStep == tAxis.size()) currentStep = 0; 159 | Keyframe::getColorForAxis(tAxis[currentStep], color); 160 | color *= colorMultiplier; 161 | glColor4d(color.r, color.g, color.b, color.a); 162 | } 163 | 164 | //std::cout << key->projPosition.x << " " << convertY << " " << 0 << std::endl; 165 | //std::cout << "gl vertex" << std::endl; 166 | 167 | // Draw Triangle 168 | 169 | glVertex3f(key->projPosition.x, convertY, 0); 170 | //std::cout << "gl vertex 1 " << x << " " << y << " " << angle << " " << size << std::endl; 171 | glVertex3f(key->projPosition.x + x, convertY + y, 0.0f); 172 | 173 | angle += angleAdd; 174 | x = size * 0.5 * sin(angle); 175 | y = size * 0.5 * cos(angle); 176 | //std::cout << "gl vertex 2 " << x << " " << y << " " << size << " " << angle << " " << angleAdd << std::endl; 177 | glVertex3f(key->projPosition.x + x, convertY + y, 0.0f); 178 | 179 | } 180 | 181 | glEnd(); 182 | //std::cout << "end triangle" << std::endl; 183 | } 184 | 185 | if (rAxis.size() > 0) 186 | { 187 | double lineWidth = size / 5; 188 | if (lineWidth < 1) lineWidth = 1; 189 | 190 | double unit = size * blackBackgroundFactor / 2; 191 | float x1s[3] = {-unit * 0.8, unit * 1.5, unit * -1.5}; 192 | float y1s[3] = {unit * 1.2, unit * 0.1, unit * 0.1}; 193 | 194 | float x2s[3] = {unit * 0.8, unit * 0.7, unit * -0.7}; 195 | float y2s[3] = {unit * 1.2, unit * -1.2, unit * -1.2}; 196 | 197 | MColor color; 198 | MVector p1(0,0,0), p2(0,0,0); 199 | for (unsigned int i = 0; i < rAxis.size(); ++i) 200 | { 201 | Keyframe::getColorForAxis(rAxis[i], color); 202 | color *= colorMultiplier; 203 | 204 | p1.x = key->projPosition.x + x1s[i]; 205 | p1.y = convertY + y1s[i]; 206 | 207 | p2.x = key->projPosition.x + x2s[i]; 208 | p2.y = convertY + y2s[i]; 209 | 210 | drawLineWithColor(p1, p2, lineWidth, color); 211 | } 212 | } 213 | } 214 | 215 | glMatrixMode(GL_PROJECTION); 216 | glPopMatrix(); 217 | glMatrixMode(GL_MODELVIEW); 218 | glPopMatrix(); 219 | } 220 | 221 | void drawUtils::drawKeyFramePoints(KeyframeMap &keyframesCache, const float size, const double colorMultiplier,const int portWidth, const int portHeight, const bool showRotationKeyframes) 222 | { 223 | glMatrixMode(GL_MODELVIEW); //combinazione matrici model e inversa camera 224 | glPushMatrix(); 225 | glMatrixMode(GL_PROJECTION); 226 | glPushMatrix(); 227 | 228 | double modelview_matrix[16]; 229 | glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix); 230 | double projection_matrix[16]; 231 | glGetDoublev(GL_PROJECTION_MATRIX, projection_matrix); 232 | int viewport[4]; 233 | glGetIntegerv(GL_VIEWPORT, viewport); 234 | 235 | std::vector keys; 236 | keys.reserve(keyframesCache.size()); 237 | for(KeyframeMapIterator keyIt = keyframesCache.begin(); keyIt != keyframesCache.end(); keyIt++) 238 | { 239 | Keyframe* key = &keyIt->second; 240 | if (!key) 241 | continue; 242 | gluProject(key->worldPosition.x, key->worldPosition.y, key->worldPosition.z, modelview_matrix, projection_matrix, viewport, &key->projPosition.x, &key->projPosition.y, &key->projPosition.z); 243 | keys.push_back(key); 244 | } 245 | 246 | glMatrixMode(GL_PROJECTION); 247 | glPopMatrix(); 248 | glMatrixMode(GL_MODELVIEW); 249 | glPopMatrix(); 250 | 251 | drawKeyFrames(keys, size, colorMultiplier, portWidth, portHeight, showRotationKeyframes); 252 | } 253 | 254 | void drawUtils::convertWorldSpaceToCameraSpace(CameraCache* cachePtr, std::map &positions, std::map &screenSpacePositions) 255 | { 256 | glMatrixMode(GL_MODELVIEW); //combinazione matrici model e inversa camera 257 | glPushMatrix(); 258 | glMatrixMode(GL_PROJECTION); 259 | glPushMatrix(); 260 | 261 | double modelview_matrix[16]; 262 | glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix); 263 | double projection_matrix[16]; 264 | glGetDoublev(GL_PROJECTION_MATRIX, projection_matrix); 265 | int viewport[4]; 266 | glGetIntegerv(GL_VIEWPORT, viewport); 267 | 268 | for(std::map::iterator it = positions.begin(); it != positions.end(); it++) 269 | { 270 | MPoint* point = &it->second; 271 | if (!point) 272 | continue; 273 | 274 | MPoint temp; 275 | gluProject(point->x, point->y, point->z, modelview_matrix, projection_matrix, viewport, &temp.x, &temp.y, &temp.z); 276 | 277 | MPoint *cp = &screenSpacePositions[it->first]; 278 | cp->x = temp.x; 279 | cp->y = temp.y; 280 | cp->z = temp.z; 281 | } 282 | 283 | glMatrixMode(GL_PROJECTION); 284 | glPopMatrix(); 285 | glMatrixMode(GL_MODELVIEW); 286 | glPopMatrix(); 287 | } 288 | 289 | void drawUtils::drawFrameLabel(double frame, const MVector &framePos, M3dView &view, const double sizeOffset, const MColor &color, const MMatrix &refMatrix) 290 | { 291 | glColor4d(color.r, color.g, color.b, color.a); 292 | 293 | MVector cameraUp(refMatrix(1, 0), refMatrix(1, 1), refMatrix(1, 2)); 294 | 295 | short viewX, viewY; 296 | view.worldToView(framePos, viewX, viewY); 297 | 298 | MPoint point1; 299 | MVector vec1; 300 | view.viewToWorld(viewX, viewY + short(GlobalSettings::frameSize * sizeOffset), point1, vec1); 301 | 302 | double distance = (framePos - point1).length(); 303 | 304 | vec1 *= distance; 305 | 306 | point1 += vec1; 307 | 308 | double up = (framePos - point1).length(); 309 | 310 | MString frameStr; 311 | frameStr = frame; 312 | 313 | MPoint textPos = framePos + (cameraUp * up); 314 | view.drawText(frameStr, textPos, M3dView::kCenter); 315 | } 316 | 317 | /* 318 | void drawUtils::drawCameraSpacePointWithColor(CameraCache *cachePtr, const MColor &color, const MPoint &position, const double size) 319 | { 320 | if (position.z > 1 || position.z < 0) 321 | return; 322 | 323 | glMatrixMode(GL_MODELVIEW); //combinazione matrici model e inversa camera 324 | glPushMatrix(); 325 | glMatrixMode(GL_PROJECTION); 326 | glPushMatrix(); 327 | 328 | glMatrixMode(GL_PROJECTION); 329 | glLoadIdentity(); 330 | glOrtho(0.0, cachePtr->portWidth, cachePtr->portHeight, 0, 1, -1); 331 | 332 | glMatrixMode(GL_MODELVIEW); 333 | glLoadIdentity(); 334 | 335 | drawUtils::drawPointWithColor(MVector(position.x, cachePtr->portHeight - position.y, 0), size, color); 336 | 337 | glMatrixMode(GL_PROJECTION); 338 | glPopMatrix(); 339 | glMatrixMode(GL_MODELVIEW); 340 | glPopMatrix(); 341 | } 342 | 343 | void drawUtils::drawCameraSpaceFramesForSelection(M3dView &view, CameraCache *cachePtr, std::map &frameScreenSpacePositions) 344 | { 345 | glMatrixMode(GL_MODELVIEW); //combinazione matrici model e inversa camera 346 | glPushMatrix(); 347 | glMatrixMode(GL_PROJECTION); 348 | glPushMatrix(); 349 | 350 | glMatrixMode(GL_PROJECTION); 351 | glLoadIdentity(); 352 | glOrtho(0.0, cachePtr->portWidth, cachePtr->portHeight, 0, 1, -1); 353 | 354 | glMatrixMode(GL_MODELVIEW); 355 | glLoadIdentity(); 356 | 357 | for (std::map::iterator it = frameScreenSpacePositions.begin(); it != frameScreenSpacePositions.end(); ++it) 358 | { 359 | if (it->second.z > 1 || it->second.z < 0) 360 | continue; 361 | 362 | view.pushName(static_cast(it->first)); 363 | 364 | MVector temp(it->second.x, cachePtr->portHeight - it->second.y, 0); 365 | drawUtils::drawPoint(temp, GlobalSettings::frameSize); 366 | view.popName(); 367 | } 368 | 369 | glMatrixMode(GL_PROJECTION); 370 | glPopMatrix(); 371 | glMatrixMode(GL_MODELVIEW); 372 | glPopMatrix(); 373 | } 374 | 375 | void drawUtils::drawCameraSpaceKeyFramesForSelection(M3dView &view, CameraCache *cachePtr, KeyframeMap &keyframesCache) 376 | { 377 | 378 | glMatrixMode(GL_MODELVIEW); //combinazione matrici model e inversa camera 379 | glPushMatrix(); 380 | glMatrixMode(GL_PROJECTION); 381 | glPushMatrix(); 382 | 383 | glMatrixMode(GL_PROJECTION); 384 | glLoadIdentity(); 385 | glOrtho(0.0, cachePtr->portWidth, cachePtr->portHeight, 0, 1, -1); 386 | 387 | glMatrixMode(GL_MODELVIEW); 388 | glLoadIdentity(); 389 | 390 | for(KeyframeMapIterator keyIt = keyframesCache.begin(); keyIt != keyframesCache.end(); keyIt++) 391 | { 392 | Keyframe* key = &keyIt->second; 393 | if (key->projPosition.z > 1 || key->projPosition.z < 0) 394 | continue; 395 | 396 | view.pushName(key->id); 397 | MVector temp(key->projPosition.x, cachePtr->portHeight - key->projPosition.y, 0); 398 | drawUtils::drawPoint(temp, GlobalSettings::frameSize * 1.2); 399 | view.popName(); 400 | } 401 | 402 | glMatrixMode(GL_PROJECTION); 403 | glPopMatrix(); 404 | glMatrixMode(GL_MODELVIEW); 405 | glPopMatrix(); 406 | } 407 | 408 | void drawUtils::drawCameraSpaceFrames(CameraCache* cachePtr, const MColor &color, std::map &positions, const double startFrame, const double endFrame) 409 | { 410 | glMatrixMode(GL_MODELVIEW); //combinazione matrici model e inversa camera 411 | glPushMatrix(); 412 | glMatrixMode(GL_PROJECTION); 413 | glPushMatrix(); 414 | 415 | glMatrixMode(GL_PROJECTION); 416 | glLoadIdentity(); 417 | glOrtho(0.0, cachePtr->portWidth, cachePtr->portHeight, 0, 1, -1); 418 | 419 | glMatrixMode(GL_MODELVIEW); 420 | glLoadIdentity(); 421 | 422 | MVector previousPosition = positions[startFrame]; 423 | for (double i = startFrame+1; i <= endFrame; ++i) 424 | { 425 | MVector point = positions[i]; 426 | if (point.z > 1 || point.z < 0 || previousPosition.z > 1 || previousPosition.z < 0) 427 | { 428 | previousPosition = point; 429 | continue; 430 | } 431 | 432 | MVector tempPrev(previousPosition.x, cachePtr->portHeight - previousPosition.y, 0); 433 | MVector temp(point.x, cachePtr->portHeight - point.y, 0); 434 | 435 | if (GlobalSettings::showPath) 436 | { 437 | double factor = 1; 438 | if (GlobalSettings::alternatingFrames) 439 | factor = int(i) % 2 == 1 ? 1.4 : 0.6; 440 | 441 | drawUtils::drawLineWithColor(tempPrev, temp, GlobalSettings::pathSize, color * factor); 442 | } 443 | 444 | drawPointWithColor(tempPrev, GlobalSettings::frameSize, color); 445 | previousPosition = point; 446 | 447 | if (i == endFrame) 448 | drawUtils::drawPointWithColor(temp, GlobalSettings::frameSize, color); 449 | 450 | } 451 | 452 | glMatrixMode(GL_PROJECTION); 453 | glPopMatrix(); 454 | glMatrixMode(GL_MODELVIEW); 455 | glPopMatrix(); 456 | } 457 | 458 | void drawUtils::convertKeyFrameTangentsToCameraSpace(CameraCache *cachePtr, KeyframeMap &keyframesCache, const MMatrix ¤tCameraMatrix) 459 | { 460 | glMatrixMode(GL_MODELVIEW); //combinazione matrici model e inversa camera 461 | glPushMatrix(); 462 | glMatrixMode(GL_PROJECTION); 463 | glPushMatrix(); 464 | 465 | double modelview_matrix[16]; 466 | glGetDoublev(GL_MODELVIEW_MATRIX, modelview_matrix); 467 | double projection_matrix[16]; 468 | glGetDoublev(GL_PROJECTION_MATRIX, projection_matrix); 469 | int viewport[4]; 470 | glGetIntegerv(GL_VIEWPORT, viewport); 471 | 472 | MVector tempIn; 473 | for(KeyframeMapIterator keyIt = keyframesCache.begin(); keyIt != keyframesCache.end(); keyIt++) 474 | { 475 | Keyframe* key = &keyIt->second; 476 | if (!key) 477 | continue; 478 | 479 | if (key->showInTangent) 480 | gluProject(key->inTangentScreenSpace.x, key->inTangentScreenSpace.y, key->inTangentScreenSpace.z, modelview_matrix, projection_matrix, viewport, &key->inTangentProjected.x, &key->inTangentProjected.y, &key->inTangentProjected.z); 481 | 482 | if (key->showOutTangent) 483 | gluProject(key->outTangentScreenSpace.x, key->outTangentScreenSpace.y, key->outTangentScreenSpace.z, modelview_matrix, projection_matrix, viewport, &key->outTangentProjected.x, &key->outTangentProjected.y, &key->outTangentProjected.z); 484 | } 485 | 486 | glMatrixMode(GL_PROJECTION); 487 | glPopMatrix(); 488 | glMatrixMode(GL_MODELVIEW); 489 | glPopMatrix(); 490 | } 491 | 492 | void drawUtils::drawCameraSpaceKeyFrameTangents(CameraCache *cachePtr, KeyframeMap &keyframesCache) 493 | { 494 | glMatrixMode(GL_MODELVIEW); //combinazione matrici model e inversa camera 495 | glPushMatrix(); 496 | glMatrixMode(GL_PROJECTION); 497 | glPushMatrix(); 498 | 499 | glMatrixMode(GL_PROJECTION); 500 | glLoadIdentity(); 501 | glOrtho(0.0, cachePtr->portWidth, cachePtr->portHeight, 0, 1, -1); 502 | 503 | glMatrixMode(GL_MODELVIEW); 504 | glLoadIdentity(); 505 | 506 | MColor tangentColor; 507 | for(KeyframeMapIterator keyIt = keyframesCache.begin(); keyIt != keyframesCache.end(); keyIt++) 508 | { 509 | Keyframe* key = &keyIt->second; 510 | if (!key) 511 | continue; 512 | 513 | if (key->projPosition.z > 1 || key->projPosition.z < 0) 514 | continue; 515 | 516 | tangentColor = key->tangentsLocked ? GlobalSettings::tangentColor : GlobalSettings::brokenTangentColor; 517 | 518 | MVector p = key->projPosition; 519 | p.y = cachePtr->portHeight - key->projPosition.y; 520 | p.z = 0; 521 | 522 | if (key->showInTangent) 523 | { 524 | MVector inT = key->inTangentProjected; 525 | inT.y = cachePtr->portHeight - key->inTangentProjected.y; 526 | inT.z = 0; 527 | 528 | drawUtils::drawLineWithColor(p, inT, 1.0, tangentColor); 529 | drawUtils::drawPointWithColor(inT, GlobalSettings::frameSize, tangentColor); 530 | } 531 | 532 | if (key->showOutTangent) 533 | { 534 | MVector outT = key->outTangentProjected; 535 | outT.y = cachePtr->portHeight - key->outTangentProjected.y; 536 | outT.z = 0; 537 | 538 | drawUtils::drawLineWithColor(p, outT, 1.0, tangentColor); 539 | drawUtils::drawPointWithColor(outT, GlobalSettings::frameSize, tangentColor); 540 | } 541 | 542 | } 543 | 544 | glMatrixMode(GL_PROJECTION); 545 | glPopMatrix(); 546 | glMatrixMode(GL_MODELVIEW); 547 | glPopMatrix(); 548 | 549 | } 550 | 551 | void drawUtils::drawCameraSpaceKeyFrameTangentsForSelection(M3dView &view, CameraCache *cachePtr, KeyframeMap &keyframesCache) 552 | { 553 | glMatrixMode(GL_MODELVIEW); //combinazione matrici model e inversa camera 554 | glPushMatrix(); 555 | glMatrixMode(GL_PROJECTION); 556 | glPushMatrix(); 557 | 558 | glMatrixMode(GL_PROJECTION); 559 | glLoadIdentity(); 560 | glOrtho(0.0, cachePtr->portWidth, cachePtr->portHeight, 0, 1, -1); 561 | 562 | glMatrixMode(GL_MODELVIEW); 563 | glLoadIdentity(); 564 | 565 | for(KeyframeMapIterator keyIt = keyframesCache.begin(); keyIt != keyframesCache.end(); keyIt++) 566 | { 567 | Keyframe* key = &keyIt->second; 568 | if (key->projPosition.z > 1 || key->projPosition.z < 0) 569 | continue; 570 | 571 | view.pushName(key->id); 572 | 573 | if (key->showInTangent) 574 | { 575 | view.pushName((int)Keyframe::kInTangent); 576 | MVector temp(key->inTangentProjected.x, cachePtr->portHeight - key->inTangentProjected.y, 0); 577 | drawUtils::drawPoint(temp, GlobalSettings::frameSize); 578 | view.popName(); 579 | } 580 | 581 | if (key->showOutTangent) 582 | { 583 | view.pushName((int)Keyframe::kOutTangent); 584 | MVector temp(key->outTangentProjected.x, cachePtr->portHeight - key->outTangentProjected.y, 0); 585 | drawUtils::drawPoint(temp, GlobalSettings::frameSize); 586 | view.popName(); 587 | } 588 | 589 | view.popName(); 590 | } 591 | 592 | glMatrixMode(GL_PROJECTION); 593 | glPopMatrix(); 594 | glMatrixMode(GL_MODELVIEW); 595 | glPopMatrix(); 596 | } 597 | */ 598 | -------------------------------------------------------------------------------- /source/GlobalSettings.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "GlobalSettings.h" 3 | 4 | double GlobalSettings::startTime = 0.0; 5 | double GlobalSettings::endTime = 0.0; 6 | double GlobalSettings::framesFront = 0; 7 | double GlobalSettings::framesBack = 0; 8 | MColor GlobalSettings::pathColor = MColor(0.5, 0.5, 0.8); 9 | MColor GlobalSettings::currentFrameColor = MColor(0.8, 0.8, 0.1); 10 | MColor GlobalSettings::tangentColor = MColor(0.5, 0.7, 0.1); 11 | MColor GlobalSettings::brokenTangentColor = MColor(0.1, 0.5, 0.7); 12 | MColor GlobalSettings::bufferPathColor = MColor(0.2, 0.2, 0.2); 13 | MColor GlobalSettings::weightedPathTangentColor = MColor(0.2, 0.2, 0.2); 14 | MColor GlobalSettings::weightedPathColor = MColor(0.2, 0.2, 0.2); 15 | MColor GlobalSettings::frameLabelColor = MColor(0.1, 0.1, 0.1); 16 | double GlobalSettings::pathSize = 3.0; 17 | double GlobalSettings::frameSize = 7.0; 18 | bool GlobalSettings::showTangents = true; 19 | bool GlobalSettings::showKeyFrames = true; 20 | bool GlobalSettings::showKeyFrameNumbers = false; 21 | bool GlobalSettings::showFrameNumbers = false; 22 | bool GlobalSettings::showRotationKeyFrames = true; 23 | bool GlobalSettings::showPath = true; 24 | double GlobalSettings::drawTimeInterval = 0.1; 25 | int GlobalSettings::drawFrameInterval = 5; 26 | MMatrix GlobalSettings::cameraMatrix; 27 | int GlobalSettings::portWidth = 0; 28 | int GlobalSettings::portHeight = 0; 29 | bool GlobalSettings::lockedMode = false; 30 | bool GlobalSettings::enabled = false; 31 | bool GlobalSettings::alternatingFrames = false; 32 | bool GlobalSettings::lockedModeInteractive = true; 33 | bool GlobalSettings::usePivots = false; 34 | int GlobalSettings::strokeMode = 0; 35 | GlobalSettings::DrawMode GlobalSettings::motionPathDrawMode = GlobalSettings::kWorldSpace; 36 | -------------------------------------------------------------------------------- /source/KeyClipboard.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // KeyClipboard.cpp 3 | // MotionPath 4 | // 5 | // Created by Daniele Federico on 27/01/15. 6 | // 7 | // 8 | 9 | #include "MotionPath.h" 10 | #include "KeyClipboard.h" 11 | 12 | KeyCopy::KeyCopy() 13 | { 14 | deltaTime = 0.0; 15 | 16 | //we need to store these as well, as otherwise we would be missing some extra information which we need when setting weighted keys 17 | xInX = xOutX = xInY = xOutY = xInZ = xOutZ = 0; 18 | wInX = wOutX = wInY = wOutY = wInZ = wOutZ = 0; 19 | 20 | hasKeyX = hasKeyY = hasKeyZ = false; 21 | tangentsLockedX = tangentsLockedY = tangentsLockedZ = true; 22 | weightsLockedX = weightsLockedY = weightsLockedZ = true; 23 | } 24 | 25 | void KeyCopy::copyKeyTangentStatus(MFnAnimCurve &curve, unsigned int keyId, const Keyframe::Axis axis) 26 | { 27 | bool tangentsLocked = curve.tangentsLocked(keyId); 28 | bool weightLocked = curve.weightsLocked(keyId); 29 | MFnAnimCurve::TangentType tin = curve.inTangentType(keyId); 30 | MFnAnimCurve::TangentType tout = curve.outTangentType(keyId); 31 | 32 | //WE NEED TO STORE THE EXTRA VALUES IN NON WEIGHTED MODE AND IN WEIGHTED MODE 33 | //THIS IS BECAUSE WE DO NOT KNOW IF THE THE DESTINATION CURVE IS WEIGHTED OR NOT 34 | 35 | bool isWeighted = curve.isWeighted(); 36 | 37 | MAngle angle; 38 | #if defined(MAYA2018) 39 | MFnAnimCurve::TangentValue y; 40 | #else 41 | float y; 42 | #endif 43 | switch (axis) 44 | { 45 | case Keyframe::kAxisX: 46 | tangentsLockedX = tangentsLocked; 47 | weightsLockedX = weightLocked; 48 | 49 | curve.setIsWeighted(true); 50 | curve.getTangent(keyId, xInX, y, Keyframe::kInTangent); 51 | curve.getTangent(keyId, xOutX, y, Keyframe::kOutTangent); 52 | curve.setIsWeighted(false); 53 | curve.getTangent(keyId, angle, wInX, Keyframe::kInTangent); 54 | curve.getTangent(keyId, angle, wOutX, Keyframe::kOutTangent); 55 | 56 | tinX = tin; 57 | toutX = tout; 58 | break; 59 | 60 | case Keyframe::kAxisY: 61 | tangentsLockedY = tangentsLocked; 62 | weightsLockedY = weightLocked; 63 | 64 | curve.setIsWeighted(true); 65 | curve.getTangent(keyId, xInY, y, Keyframe::kInTangent); 66 | curve.getTangent(keyId, xOutY, y, Keyframe::kOutTangent); 67 | curve.setIsWeighted(false); 68 | curve.getTangent(keyId, angle, wInY, Keyframe::kInTangent); 69 | curve.getTangent(keyId, angle, wOutY, Keyframe::kOutTangent); 70 | 71 | tinY = tin; 72 | toutY = tout; 73 | break; 74 | 75 | case Keyframe::kAxisZ: 76 | tangentsLockedZ = tangentsLocked; 77 | weightsLockedZ = weightLocked; 78 | 79 | curve.setIsWeighted(true); 80 | curve.getTangent(keyId, xInZ, y, Keyframe::kInTangent); 81 | curve.getTangent(keyId, xOutZ, y, Keyframe::kOutTangent); 82 | curve.setIsWeighted(false); 83 | curve.getTangent(keyId, angle, wInZ, Keyframe::kInTangent); 84 | curve.getTangent(keyId, angle, wOutZ, Keyframe::kOutTangent); 85 | 86 | tinZ = tin; 87 | toutZ = tout; 88 | break; 89 | } 90 | 91 | //setting back the initial curve state 92 | curve.setIsWeighted(isWeighted); 93 | } 94 | 95 | void KeyCopy::addKeyFrame(MFnAnimCurve &cx, MFnAnimCurve &cy, MFnAnimCurve &cz, const MTime &time, const MVector &pos, const bool isBoundary, MAnimCurveChange *change) 96 | { 97 | unsigned int keyID; 98 | 99 | // we break the tangents as they could be various, we are going to restore their state in the setTangents method 100 | 101 | if (hasKeyX || isBoundary) 102 | { 103 | if (!cx.find(time, keyID)) 104 | keyID = cx.addKey(time, pos.x, tinX, toutX, change); 105 | else 106 | cx.setValue(keyID, pos.x, change); 107 | 108 | cx.setTangentsLocked(keyID, false, change); 109 | cx.setWeightsLocked(keyID, false, change); 110 | } 111 | 112 | if (hasKeyY || isBoundary) 113 | { 114 | if (!cy.find(time, keyID)) 115 | keyID = cy.addKey(time, pos.y, tinY, toutY, change); 116 | else 117 | cy.setValue(keyID, pos.y, change); 118 | 119 | cy.setTangentsLocked(keyID, false, change); 120 | cy.setWeightsLocked(keyID, false, change); 121 | } 122 | 123 | if (hasKeyZ || isBoundary) 124 | { 125 | if (!cz.find(time, keyID)) 126 | keyID = cz.addKey(time, pos.z, tinZ, toutZ, change); 127 | else 128 | cz.setValue(keyID, pos.z, change); 129 | 130 | cz.setTangentsLocked(keyID, false, change); 131 | cz.setWeightsLocked(keyID, false, change); 132 | } 133 | 134 | } 135 | 136 | void KeyCopy::setTangent(MFnAnimCurve &curve, const float value, const unsigned int keyID, const double weight, const float x, const bool inTangent, const bool wasWeighted, MAnimCurveChange *change) 137 | { 138 | if (!curve.isWeighted()) 139 | { 140 | MAngle angle(atan(value*weight)); 141 | curve.setTangent(keyID, angle, weight, inTangent, change); 142 | } 143 | else 144 | { 145 | float y = value * 3.0; 146 | 147 | MTime convert(1.0, MTime::kSeconds); 148 | float _x = x * (float) convert.as(MTime::uiUnit()); 149 | 150 | curve.setTangent(keyID, _x, y, inTangent, change); 151 | } 152 | } 153 | 154 | void KeyCopy::setTangents(MFnAnimCurve &cx, MFnAnimCurve &cy, MFnAnimCurve &cz, const MMatrix &pMatrix, const MTime &time, const bool isBoundary, const bool modifyInTangent, const bool modifyOutTangent, const bool breakTangentsX, const bool breakTangentsY, const bool breakTangentsZ, const bool xWasWeighted, const bool yWasWeighted, const bool zWasWeighted, MAnimCurveChange *change) 155 | { 156 | unsigned int keyID; 157 | MVector in = (inWorldTangent - worldPos) * pMatrix; 158 | MVector out = (outWorldTangent - worldPos) * pMatrix; 159 | MVector inWeighted = (inWeightedWorldTangent - worldPos) * pMatrix; 160 | MVector outWeighted = (outWeightedWorldTangent - worldPos) * pMatrix; 161 | 162 | //we want to edit the out tanget, only when they are broken or we must modify the out tangent or we didn't modify the in tangent 163 | 164 | float inValue, outValue; 165 | if (hasKeyX || isBoundary) 166 | { 167 | if (cx.isWeighted()) 168 | { 169 | inValue = inWeighted.x; 170 | outValue = outWeighted.x; 171 | } 172 | else 173 | { 174 | inValue = in.x; 175 | outValue = out.x; 176 | } 177 | 178 | 179 | cx.find(time, keyID); 180 | if (modifyInTangent) 181 | setTangent(cx, -inValue, keyID, wInX, xInX, true, xWasWeighted, change); 182 | if (modifyOutTangent) 183 | setTangent(cx, outValue, keyID, wOutX, xOutX, false, xWasWeighted, change); 184 | 185 | if (breakTangentsX) 186 | cx.setTangentsLocked(keyID, false, change); 187 | else 188 | cx.setTangentsLocked(keyID, tangentsLockedX, change); 189 | cx.setWeightsLocked(keyID, weightsLockedX, change); 190 | } 191 | 192 | if (hasKeyY || isBoundary) 193 | { 194 | if (cy.isWeighted()) 195 | { 196 | inValue = inWeighted.y; 197 | outValue = outWeighted.y; 198 | } 199 | else 200 | { 201 | inValue = in.y; 202 | outValue = out.y; 203 | } 204 | 205 | cy.find(time, keyID); 206 | 207 | if (modifyInTangent) 208 | setTangent(cy, -inValue, keyID, wInY, xInY, true, yWasWeighted, change); 209 | if (modifyOutTangent) 210 | setTangent(cy, outValue, keyID, wOutY, xOutY, false, yWasWeighted, change); 211 | 212 | if (breakTangentsY) 213 | cy.setTangentsLocked(keyID, false, change); 214 | else 215 | cy.setTangentsLocked(keyID, tangentsLockedY, change); 216 | cy.setWeightsLocked(keyID, weightsLockedY, change); 217 | } 218 | 219 | if (hasKeyZ || isBoundary) 220 | { 221 | if (cz.isWeighted()) 222 | { 223 | inValue = inWeighted.z; 224 | outValue = outWeighted.z; 225 | } 226 | else 227 | { 228 | inValue = in.z; 229 | outValue = out.z; 230 | } 231 | 232 | cz.find(time, keyID); 233 | 234 | if (modifyInTangent) 235 | setTangent(cz, -in.z, keyID, wInZ, xInZ, true, zWasWeighted, change); 236 | if (modifyOutTangent) 237 | setTangent(cz, out.z, keyID, wOutZ, xOutZ, false, zWasWeighted, change); 238 | 239 | if (breakTangentsZ) 240 | cz.setTangentsLocked(keyID, false, change); 241 | else 242 | cz.setTangentsLocked(keyID, tangentsLockedZ, change); 243 | cz.setWeightsLocked(keyID, weightsLockedZ, change); 244 | } 245 | } 246 | 247 | -------------------------------------------------------------------------------- /source/Keyframe.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "Keyframe.h" 3 | 4 | Keyframe::Keyframe() 5 | { 6 | this->id = -1; 7 | this->time = 0.0; 8 | this->tangentsLocked = true; 9 | this->xKeyId = -1; 10 | this->yKeyId = -1; 11 | this->zKeyId = -1; 12 | this->xRotKeyId = -1; 13 | this->yRotKeyId = -1; 14 | this->zRotKeyId = -1; 15 | this->showInTangent = true; 16 | this->showOutTangent = true; 17 | this->selectedFromTool = false; 18 | } 19 | 20 | 21 | bool Keyframe::hasTranslationXYZ() 22 | { 23 | return (this->xKeyId != -1 && this->yKeyId != -1 && this->zKeyId != -1); 24 | } 25 | 26 | bool Keyframe::hasRotationXYZ() 27 | { 28 | return (this->xRotKeyId != -1 && this->yRotKeyId != -1 && this->zRotKeyId != -1); 29 | } 30 | 31 | void Keyframe::setTangentValue(double value, const Keyframe::Axis &axisName, const Keyframe::Tangent &tangentName) 32 | { 33 | switch(axisName) 34 | { 35 | case Keyframe::kAxisX: 36 | if(tangentName == Keyframe::kInTangent) 37 | this->inTangent.x = value; 38 | else 39 | this->outTangent.x = value; 40 | break; 41 | 42 | case Keyframe::kAxisY: 43 | if(tangentName == Keyframe::kInTangent) 44 | this->inTangent.y = value; 45 | else 46 | this->outTangent.y = value; 47 | break; 48 | 49 | case Keyframe::kAxisZ: 50 | if(tangentName == Keyframe::kInTangent) 51 | this->inTangent.z = value; 52 | else 53 | this->outTangent.z = value; 54 | break; 55 | } 56 | } 57 | 58 | void Keyframe::setTangent(int keyIndex, const MFnAnimCurve &curve, const Keyframe::Axis &axisName, const Keyframe::Tangent &tangentName) 59 | { 60 | double tangentVal = 0.0; 61 | if(!curve.isWeighted()) 62 | { 63 | MAngle angle; 64 | double w1; 65 | curve.getTangent(keyIndex, angle, w1, tangentName); 66 | tangentVal = tan(angle.asRadians()) * w1; 67 | } 68 | else 69 | { 70 | #if defined(MAYA2018) 71 | MFnAnimCurve::TangentValue x, y; 72 | #else 73 | float x, y; 74 | #endif 75 | curve.getTangent(keyIndex, x, y, tangentName); 76 | tangentVal = y / 3.0; // divide by the number of curves 77 | } 78 | 79 | this->setTangentValue(tangentVal, axisName, tangentName); 80 | } 81 | 82 | void Keyframe::setKeyId(int id, const Keyframe::Axis &axisName) 83 | { 84 | switch(axisName) 85 | { 86 | case Keyframe::kAxisX: 87 | this->xKeyId = id; 88 | break; 89 | 90 | case Keyframe::kAxisY: 91 | this->yKeyId = id; 92 | break; 93 | 94 | case Keyframe::kAxisZ: 95 | this->zKeyId = id; 96 | break; 97 | } 98 | } 99 | 100 | void Keyframe::setRotKeyId(int id, const Keyframe::Axis &axisName) 101 | { 102 | switch(axisName) 103 | { 104 | case Keyframe::kAxisX: 105 | this->xRotKeyId = id; 106 | break; 107 | 108 | case Keyframe::kAxisY: 109 | this->yRotKeyId = id; 110 | break; 111 | 112 | case Keyframe::kAxisZ: 113 | this->zRotKeyId = id; 114 | break; 115 | } 116 | } 117 | 118 | void Keyframe::getKeyTranslateAxis(std::vector &axis) 119 | { 120 | if (xKeyId != -1) 121 | axis.push_back(Keyframe::kAxisX); 122 | 123 | if (yKeyId != -1) 124 | axis.push_back(Keyframe::kAxisY); 125 | 126 | if (zKeyId != -1) 127 | axis.push_back(Keyframe::kAxisZ); 128 | } 129 | 130 | void Keyframe::getKeyRotateAxis(std::vector &axis) 131 | { 132 | if (xRotKeyId != -1) 133 | axis.push_back(Keyframe::kAxisX); 134 | 135 | if (yRotKeyId != -1) 136 | axis.push_back(Keyframe::kAxisY); 137 | 138 | if (zRotKeyId != -1) 139 | axis.push_back(Keyframe::kAxisZ); 140 | } 141 | 142 | void Keyframe::getColorForAxis(const Keyframe::Axis axis, MColor &color) 143 | { 144 | switch(axis) 145 | { 146 | case Keyframe::kAxisX: 147 | color.r = 1.0; color.g = 0.0; color.b = 0.0; 148 | break; 149 | 150 | case Keyframe::kAxisY: 151 | color.r = 0.0; color.g = 1.0; color.b = 0.0; 152 | break; 153 | 154 | case Keyframe::kAxisZ: 155 | color.r = 0.0; color.g = 0.0; color.b = 1.0; 156 | break; 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /source/MotionPathCmd.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "MotionPathCmd.h" 4 | 5 | extern MotionPathManager mpManager; 6 | 7 | 8 | void* MotionPathCmd::creator() 9 | { 10 | return new MotionPathCmd; 11 | } 12 | 13 | MotionPathCmd::MotionPathCmd() 14 | { 15 | this->animCurveChangePtr = NULL; 16 | this->dgModifierPtr = NULL; 17 | this->animUndoable = false; 18 | this->dgUndoable = false; 19 | this->keySelectionUndoable = false; 20 | this->selectionUndoable = false; 21 | } 22 | 23 | MotionPathCmd::~MotionPathCmd() 24 | { 25 | if (this->animCurveChangePtr) 26 | delete this->animCurveChangePtr; 27 | 28 | if (this->dgModifierPtr) 29 | delete this->dgModifierPtr; 30 | } 31 | 32 | bool MotionPathCmd::isUndoable() const 33 | { 34 | return this->animUndoable || this->dgUndoable || this->keySelectionUndoable|| this->selectionUndoable; 35 | } 36 | 37 | MColor getColorFromArg(const MArgDatabase &argData, const char *flagName) 38 | { 39 | double r, g, b; 40 | argData.getFlagArgument(flagName, 0, r); 41 | argData.getFlagArgument(flagName, 1, g); 42 | argData.getFlagArgument(flagName, 2, b); 43 | return MColor(r, g, b); 44 | } 45 | 46 | 47 | MSyntax MotionPathCmd::syntaxCreator() 48 | { 49 | MSyntax syntax; 50 | 51 | syntax.addFlag("-e", "-enable", MSyntax::kBoolean); 52 | syntax.addFlag("-gsl", "-getCurrentSL", MSyntax::kNoArg); 53 | syntax.addFlag("-rdt", "-refreshdt", MSyntax::kNoArg); 54 | 55 | syntax.addFlag("-bf", "-framesBefore", MSyntax::kLong); 56 | syntax.addFlag("-af", "-framesAfter", MSyntax::kLong); 57 | syntax.addFlag("-tfr", "-frameRange", MSyntax::kLong, MSyntax::kLong); 58 | syntax.addFlag("-st", "-showTangents", MSyntax::kBoolean); 59 | syntax.addFlag("-sp", "-showPath", MSyntax::kBoolean); 60 | syntax.addFlag("-sk", "-showKeyFrames", MSyntax::kBoolean); 61 | syntax.addFlag("-srk", "-showRotationKeyFrames", MSyntax::kBoolean); 62 | syntax.addFlag("-skn", "-showKeyFrameNumbers", MSyntax::kBoolean); 63 | syntax.addFlag("-sfn", "-showFrameNumbers", MSyntax::kBoolean); 64 | 65 | syntax.addFlag("-alf", "-alternatingFrames", MSyntax::kBoolean); 66 | syntax.addFlag("-up", "-usePivots", MSyntax::kBoolean); 67 | 68 | syntax.addFlag("-abp", "-addBufferPaths", MSyntax::kNoArg); 69 | syntax.addFlag("-dbs", "-deleteAllBufferPaths", MSyntax::kNoArg); 70 | syntax.addFlag("-dbi", "-deleteBufferPathAtIndex", MSyntax::kLong); 71 | syntax.addFlag("-sbp", "-selectBufferPathAtIndex", MSyntax::kLong); 72 | syntax.addFlag("-dbp", "-deselectBufferPathAtIndex", MSyntax::kLong); 73 | 74 | syntax.addFlag("-fs", "-frameSize", MSyntax::kDouble); 75 | syntax.addFlag("-ps", "-pathSize", MSyntax::kDouble); 76 | 77 | syntax.addFlag("-mdm", "-drawMode", MSyntax::kLong); 78 | 79 | syntax.addFlag("-cfc", "-currentFrameColor", MSyntax::kDouble, MSyntax::kDouble, MSyntax::kDouble); 80 | syntax.addFlag("-pc", "-pathColor", MSyntax::kDouble, MSyntax::kDouble, MSyntax::kDouble); 81 | syntax.addFlag("-tc", "-tangentColor", MSyntax::kDouble, MSyntax::kDouble, MSyntax::kDouble); 82 | syntax.addFlag("-btc", "-brokenTangentColor", MSyntax::kDouble, MSyntax::kDouble, MSyntax::kDouble); 83 | syntax.addFlag("-bpc", "-bufferPathColor", MSyntax::kDouble, MSyntax::kDouble, MSyntax::kDouble); 84 | syntax.addFlag("-wpc", "-weightedPathColor", MSyntax::kDouble, MSyntax::kDouble, MSyntax::kDouble); 85 | syntax.addFlag("-wtc", "-weightedPathTangentColor", MSyntax::kDouble, MSyntax::kDouble, MSyntax::kDouble); 86 | syntax.addFlag("-fnc", "-frameNumberColor", MSyntax::kDouble, MSyntax::kDouble, MSyntax::kDouble); 87 | 88 | syntax.addFlag("-dti", "-drawTimeInterval", MSyntax::kDouble); 89 | syntax.addFlag("-fi", "-frameInterval", MSyntax::kLong); 90 | syntax.addFlag("-sm", "-strokeMode", MSyntax::kLong); 91 | 92 | syntax.addFlag("-sdc", "-storeDGAndCurveChange", MSyntax::kNoArg); 93 | 94 | syntax.addFlag("-cbp", "-convertBufferPath", MSyntax::kLong); 95 | 96 | syntax.addFlag("-ksc", "-keySelectionChanged", MSyntax::kNoArg); 97 | syntax.addFlag("-sc", "-selectionChanged", MSyntax::kNoArg); 98 | 99 | syntax.addFlag("-l", "-lockedMode", MSyntax::kBoolean); 100 | syntax.addFlag("-lmi", "-lockedModeInteractive", MSyntax::kBoolean); 101 | syntax.addFlag("-rls", "-refreshLockedSelection", MSyntax::kNoArg); 102 | 103 | syntax.useSelectionAsDefault(false); 104 | syntax.setObjectType(MSyntax::kSelectionList, 0); 105 | 106 | return syntax; 107 | } 108 | 109 | MStatus MotionPathCmd::doIt(const MArgList& args) 110 | { 111 | MArgDatabase argData(syntax(), args); 112 | 113 | if(argData.isFlagSet("-enable")) 114 | { 115 | bool enable; 116 | argData.getFlagArgument("-enable", 0, enable); 117 | 118 | if(enable) 119 | { 120 | mpManager.setupViewports(); 121 | mpManager.addCallbacks(); 122 | 123 | MotionPathManager::selectionChangeCallback(&mpManager); 124 | } 125 | else 126 | { 127 | mpManager.cleanupViewports(); 128 | mpManager.removeCallbacks(); 129 | } 130 | 131 | GlobalSettings::enabled = enable; 132 | } 133 | else if(argData.isFlagSet("-getCurrentSL")) 134 | { 135 | this->setResult(mpManager.getSelectionList()); 136 | } 137 | else if(argData.isFlagSet("-frameRange")) 138 | { 139 | int initialFrame, lastFrame; 140 | argData.getFlagArgument("-frameRange", 0, initialFrame); 141 | argData.getFlagArgument("-frameRange", 1, lastFrame); 142 | mpManager.setTimeRange(initialFrame, lastFrame); 143 | } 144 | else if(argData.isFlagSet("-framesBefore")) 145 | { 146 | int beforeFrame; 147 | argData.getFlagArgument("-framesBefore", 0, beforeFrame); 148 | 149 | if (beforeFrame < 0) 150 | beforeFrame = 0; 151 | 152 | GlobalSettings::framesBack = beforeFrame; 153 | } 154 | else if(argData.isFlagSet("-framesAfter")) 155 | { 156 | int afterFrame; 157 | argData.getFlagArgument("-framesAfter", 0, afterFrame); 158 | 159 | if (afterFrame < 0) 160 | afterFrame = 0; 161 | 162 | GlobalSettings::framesFront = afterFrame; 163 | } 164 | else if(argData.isFlagSet("-rdt")) 165 | { 166 | mpManager.refreshDisplayTimeRange(); 167 | } 168 | else if(argData.isFlagSet("-showTangents")) 169 | { 170 | bool showTangents; 171 | argData.getFlagArgument("-showTangents", 0, showTangents); 172 | GlobalSettings::showTangents = showTangents; 173 | } 174 | else if(argData.isFlagSet("-showKeyFrames")) 175 | { 176 | bool showKeyFrames; 177 | argData.getFlagArgument("-showKeyFrames", 0, showKeyFrames); 178 | GlobalSettings::showKeyFrames = showKeyFrames; 179 | } 180 | else if(argData.isFlagSet("-showPath")) 181 | { 182 | bool showPath; 183 | argData.getFlagArgument("-showPath", 0, showPath); 184 | GlobalSettings::showPath = showPath; 185 | } 186 | else if (argData.isFlagSet("-showRotationKeyFrames")) 187 | { 188 | bool showRotationKeyFrames; 189 | argData.getFlagArgument("-showRotationKeyFrames", 0, showRotationKeyFrames); 190 | GlobalSettings::showRotationKeyFrames = showRotationKeyFrames; 191 | } 192 | else if (argData.isFlagSet("-showKeyFrameNumbers")) 193 | { 194 | bool showKeyFrameNumbers; 195 | argData.getFlagArgument("-showKeyFrameNumbers", 0, showKeyFrameNumbers); 196 | GlobalSettings::showKeyFrameNumbers = showKeyFrameNumbers; 197 | } 198 | else if (argData.isFlagSet("-showFrameNumbers")) 199 | { 200 | bool showFrameNumbers; 201 | argData.getFlagArgument("-showFrameNumbers", 0, showFrameNumbers); 202 | GlobalSettings::showFrameNumbers = showFrameNumbers; 203 | } 204 | else if (argData.isFlagSet("-alternatingFrames")) 205 | { 206 | bool alternatingFrames; 207 | argData.getFlagArgument("-alternatingFrames", 0, alternatingFrames); 208 | GlobalSettings::alternatingFrames = alternatingFrames; 209 | } 210 | else if (argData.isFlagSet("-usePivots")) 211 | { 212 | bool usePivots; 213 | argData.getFlagArgument("-usePivots", 0, usePivots); 214 | GlobalSettings::usePivots = usePivots; 215 | 216 | mpManager.clearParentMatrixCaches(); 217 | mpManager.refreshDisplayTimeRange(); 218 | } 219 | else if (argData.isFlagSet("-pathSize")) 220 | { 221 | double pathSize; 222 | argData.getFlagArgument("-pathSize", 0, pathSize); 223 | GlobalSettings::pathSize = pathSize; 224 | } 225 | else if (argData.isFlagSet("-frameSize")) 226 | { 227 | double frameSize; 228 | argData.getFlagArgument("-frameSize", 0, frameSize); 229 | GlobalSettings::frameSize = frameSize; 230 | } 231 | else if (argData.isFlagSet("-drawTimeInterval")) 232 | { 233 | double drawTimeInterval; 234 | argData.getFlagArgument("-drawTimeInterval", 0, drawTimeInterval); 235 | GlobalSettings::drawTimeInterval = drawTimeInterval; 236 | } 237 | else if (argData.isFlagSet("-strokeMode")) 238 | { 239 | int strokeMode; 240 | argData.getFlagArgument("-strokeMode", 0, strokeMode); 241 | GlobalSettings::strokeMode = strokeMode; 242 | } 243 | else if (argData.isFlagSet("-drawMode")) 244 | { 245 | int drawMode; 246 | argData.getFlagArgument("-drawMode", 0, drawMode); 247 | 248 | if (GlobalSettings::motionPathDrawMode != drawMode) 249 | { 250 | /* 251 | if (drawMode == 0) 252 | mpManager.destroyCameraCachesAndCameraCallbacks(); 253 | else 254 | mpManager.createCameraCachesAndCameraCallbacks(); 255 | */ 256 | 257 | if (drawMode < 0) 258 | drawMode = 0; 259 | 260 | if (drawMode > 1) 261 | drawMode = 1; 262 | 263 | mpManager.cacheCameras(); 264 | GlobalSettings::motionPathDrawMode = (GlobalSettings::DrawMode) drawMode; 265 | } 266 | } 267 | else if (argData.isFlagSet("-frameInterval")) 268 | { 269 | int frameInterval; 270 | argData.getFlagArgument("-frameInterval", 0, frameInterval); 271 | GlobalSettings::drawFrameInterval = frameInterval; 272 | } 273 | else if (argData.isFlagSet("-currentFrameColor")) 274 | { 275 | GlobalSettings::currentFrameColor = getColorFromArg(argData, "-currentFrameColor"); 276 | } 277 | else if (argData.isFlagSet("-pathColor")) 278 | { 279 | GlobalSettings::pathColor = getColorFromArg(argData, "-pathColor"); 280 | } 281 | else if (argData.isFlagSet("-tangentColor")) 282 | { 283 | GlobalSettings::tangentColor = getColorFromArg(argData, "-tangentColor"); 284 | } 285 | else if (argData.isFlagSet("-brokenTangentColor")) 286 | { 287 | GlobalSettings::brokenTangentColor = getColorFromArg(argData, "-brokenTangentColor"); 288 | } 289 | else if (argData.isFlagSet("-bufferPathColor")) 290 | { 291 | GlobalSettings::bufferPathColor = getColorFromArg(argData, "-bufferPathColor"); 292 | } 293 | else if (argData.isFlagSet("-weightedPathColor")) 294 | { 295 | GlobalSettings::weightedPathColor = getColorFromArg(argData, "-weightedPathColor"); 296 | } 297 | else if (argData.isFlagSet("-weightedPathTangentColor")) 298 | { 299 | GlobalSettings::weightedPathTangentColor = getColorFromArg(argData, "-weightedPathTangentColor"); 300 | } 301 | else if (argData.isFlagSet("-frameNumberColor")) 302 | { 303 | GlobalSettings::frameLabelColor = getColorFromArg(argData, "-frameNumberColor"); 304 | } 305 | else if (argData.isFlagSet("-addBufferPaths")) 306 | { 307 | mpManager.addBufferPaths(); 308 | } 309 | else if (argData.isFlagSet("-deleteAllBufferPaths")) 310 | { 311 | mpManager.deleteAllBufferPaths(); 312 | } 313 | else if (argData.isFlagSet("-deleteBufferPathAtIndex")) 314 | { 315 | int index; 316 | argData.getFlagArgument("-deleteBufferPathAtIndex", 0, index); 317 | mpManager.deleteBufferPathAtIndex(index); 318 | } 319 | else if (argData.isFlagSet("-selectBufferPathAtIndex")) 320 | { 321 | int index; 322 | argData.getFlagArgument("-selectBufferPathAtIndex", 0, index); 323 | mpManager.setSelectStateForBufferPathAtIndex(index, true); 324 | } 325 | else if (argData.isFlagSet("-deselectBufferPathAtIndex")) 326 | { 327 | int index; 328 | argData.getFlagArgument("-deselectBufferPathAtIndex", 0, index); 329 | mpManager.setSelectStateForBufferPathAtIndex(index, false); 330 | } 331 | else if(argData.isFlagSet("-lockedMode")) 332 | { 333 | bool value; 334 | argData.getFlagArgument("-lockedMode", 0, value); 335 | GlobalSettings::lockedMode = value; 336 | if (value) 337 | mpManager.createMotionPathWorldCallback(); 338 | else 339 | mpManager.destroyMotionPathWorldCallback(); 340 | } 341 | else if(argData.isFlagSet("-lockedModeInteractive")) 342 | { 343 | bool lockedModeInteractive; 344 | argData.getFlagArgument("-lockedModeInteractive", 0, lockedModeInteractive); 345 | GlobalSettings::lockedModeInteractive = lockedModeInteractive; 346 | } 347 | else if(argData.isFlagSet("-refreshLockedSelection")) 348 | { 349 | mpManager.clearParentMatrixCaches(); 350 | mpManager.refreshDisplayTimeRange(); 351 | } 352 | else if (argData.isFlagSet("-storeDGAndCurveChange")) 353 | { 354 | dgModifierPtr = mpManager.getDGModifierPtr(); 355 | animCurveChangePtr = mpManager.getAnimCurveChangePtr(); 356 | 357 | if(dgModifierPtr) 358 | dgUndoable = true; 359 | else 360 | dgModifierPtr = NULL; 361 | 362 | if(animCurveChangePtr) 363 | animUndoable = true; 364 | else 365 | animCurveChangePtr = NULL; 366 | } 367 | else if (argData.isFlagSet("-convertBufferPath")) 368 | { 369 | int index; 370 | argData.getFlagArgument("-convertBufferPath", 0, index); 371 | BufferPath *bp = mpManager.getBufferPathAtIndex(index); 372 | 373 | if (bp == NULL) 374 | { 375 | MGlobal::displayError("tcMotionPathCmd: wrong buffer path index given."); 376 | return MS::kFailure; 377 | } 378 | 379 | mpManager.startDGUndoRecording(); 380 | if (!createCurveFromBufferPath(bp)) 381 | { 382 | mpManager.stopDGAndAnimUndoRecording(); 383 | MGlobal::displayError("tcMotionPathCmd: could not convert curve."); 384 | return MS::kFailure; 385 | } 386 | mpManager.stopDGAndAnimUndoRecording(); 387 | } 388 | else if (argData.isFlagSet("-keySelectionChanged")) 389 | { 390 | keySelectionUndoable = true; 391 | mpManager.getPreviousKeySelection(initialSelection); 392 | mpManager.getCurrentKeySelection(finalSelection); 393 | return redoIt(); 394 | } 395 | else if(argData.isFlagSet("-selectionChanged")) 396 | { 397 | if (argData.getObjects(newSelection) == MS::kFailure) 398 | { 399 | MGlobal::displayError("tcMotionPathCmd: failed while parsing arguments"); 400 | return MS::kFailure; 401 | } 402 | 403 | selectionUndoable = true; 404 | mpManager.getPreviousKeySelection(initialSelection); 405 | MGlobal::getActiveSelectionList(oldSelection); 406 | return redoIt(); 407 | } 408 | else 409 | { 410 | MGlobal::displayError("tcMotionPathCmd: wrong flag."); 411 | return MS::kFailure; 412 | } 413 | 414 | return MS::kSuccess; 415 | } 416 | 417 | MStatus MotionPathCmd::redoIt() 418 | { 419 | if(animUndoable && animCurveChangePtr) 420 | animCurveChangePtr->redoIt(); 421 | 422 | if (dgUndoable && dgModifierPtr) 423 | dgModifierPtr->doIt(); 424 | 425 | if (keySelectionUndoable) 426 | { 427 | if (GlobalSettings::enabled) 428 | { 429 | restoreKeySelection(finalSelection); 430 | mpManager.storePreviousKeySelection(); 431 | } 432 | } 433 | 434 | if (selectionUndoable) 435 | MGlobal::setActiveSelectionList(newSelection); 436 | 437 | return MS::kSuccess; 438 | } 439 | 440 | MStatus MotionPathCmd::undoIt() 441 | { 442 | if(animUndoable && animCurveChangePtr) 443 | animCurveChangePtr->undoIt(); 444 | 445 | if (dgUndoable && dgModifierPtr) 446 | dgModifierPtr->undoIt(); 447 | 448 | if (keySelectionUndoable) 449 | { 450 | if (GlobalSettings::enabled) 451 | { 452 | restoreKeySelection(initialSelection); 453 | mpManager.storePreviousKeySelection(); 454 | } 455 | } 456 | 457 | if (selectionUndoable) 458 | { 459 | MGlobal::setActiveSelectionList(oldSelection); 460 | if (GlobalSettings::enabled) 461 | { 462 | restoreKeySelection(initialSelection); 463 | mpManager.storePreviousKeySelection(); 464 | } 465 | } 466 | 467 | return MS::kSuccess; 468 | } 469 | 470 | void MotionPathCmd::restoreKeySelection(const std::vector &sel) 471 | { 472 | for (int i = 0; i < sel.size(); ++i) 473 | { 474 | MotionPath *motionPathPtr = mpManager.getMotionPathPtr(i); 475 | if (motionPathPtr) 476 | { 477 | motionPathPtr->deselectAllKeys(); 478 | for (int j = 0; j < sel[i].length(); ++j) 479 | motionPathPtr->selectKeyAtTime(sel[i][j]); 480 | } 481 | } 482 | 483 | M3dView::active3dView().refresh(); 484 | } 485 | 486 | bool MotionPathCmd::createCurveFromBufferPath(BufferPath *bp) 487 | { 488 | const std::vector* points = bp->getFrames(); 489 | if (points == NULL) return false; 490 | 491 | MString cmd = "curve -d 1 "; 492 | MString cvsStr = ""; 493 | for (unsigned int i = 0; i < points->size(); ++i) 494 | { 495 | MVector v = points->at(i); 496 | cvsStr += MString("-p ") + v.x + " " + v.y + " " + v.z + " "; 497 | } 498 | 499 | MString knotsStr = ""; 500 | for (unsigned int i = 0; i < points->size(); i++) 501 | knotsStr += MString("-k ") + ((double) i) + " "; 502 | 503 | MDGModifier *dg = mpManager.getDGModifierPtr(); 504 | dg->commandToExecute(cmd + cvsStr + knotsStr); 505 | return dg->doIt() == MS::kSuccess; 506 | } 507 | 508 | -------------------------------------------------------------------------------- /source/MotionPathDrawContext.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // MotionPathDrawContext.cpp 3 | // MotionPath 4 | // 5 | // Created by Daniele Federico on 30/11/14. 6 | // 7 | // 8 | 9 | #include "MotionPathDrawContext.h" 10 | 11 | #include "GlobalSettings.h" 12 | #include "ContextUtils.h" 13 | 14 | extern MotionPathManager mpManager; 15 | 16 | MPxContext* MotionPathDrawContextCmd::makeObj() 17 | { 18 | return new MotionPathDrawContext(); 19 | } 20 | 21 | void* MotionPathDrawContextCmd::creator() 22 | { 23 | return new MotionPathDrawContextCmd; 24 | } 25 | 26 | MotionPathDrawContext::MotionPathDrawContext() 27 | { 28 | } 29 | 30 | void MotionPathDrawContext::toolOnSetup( MEvent& event ) 31 | { 32 | this->selectedMotionPathPtr = NULL; 33 | this->currentMode = kNoneMode; 34 | this->selectedKeyId = -1; 35 | 36 | // set the help text in the maya help boxs 37 | setHelpString("Left-Click key frame then drag to draw path; CTRL-Left-Click key frame then drag to draw proximity stroke; Middle-Click in the viewport to add a keyframe at the current time."); 38 | } 39 | 40 | void MotionPathDrawContext::toolOffCleanup() 41 | { 42 | if (selectedMotionPathPtr) 43 | { 44 | M3dView view = M3dView::active3dView(); 45 | view.refresh(); 46 | } 47 | } 48 | 49 | void MotionPathDrawContext::drawStroke() 50 | { 51 | if (strokePoints.length() < 2) 52 | return; 53 | 54 | glBegin(GL_LINE_STRIP); 55 | for (int i = 0; i < strokePoints.length(); ++i) 56 | glVertex2f(strokePoints[i].x, strokePoints[i].y); 57 | glEnd(); 58 | } 59 | 60 | void MotionPathDrawContext::drawStrokeNew(MHWRender::MUIDrawManager& drawMgr) 61 | { 62 | if (strokePoints.length() < 2) 63 | return; 64 | 65 | drawMgr.beginDrawable(); 66 | drawMgr.setLineWidth(2.0f); 67 | drawMgr.setColor(MColor(1.0, 1.0, 1.0)); 68 | for (int i = 1; i < strokePoints.length(); ++i) 69 | drawMgr.line2d(strokePoints[i-1], strokePoints[i]); 70 | 71 | drawMgr.endDrawable(); 72 | 73 | } 74 | 75 | bool MotionPathDrawContext::doPressCommon(MEvent &event, const bool old) 76 | { 77 | event.getPosition(initialX, initialY); 78 | activeView = M3dView::active3dView(); 79 | 80 | if (!GlobalSettings::showKeyFrames) 81 | return false; 82 | 83 | MDagPath camera; 84 | activeView.getCamera(camera); 85 | MMatrix cameraMatrix = camera.inclusiveMatrix(); 86 | cameraPosition.x = cameraMatrix(3, 0); 87 | cameraPosition.y = cameraMatrix(3, 1), 88 | cameraPosition.z = cameraMatrix(3, 2); 89 | 90 | inverseCameraMatrix = cameraMatrix.inverse(); 91 | 92 | if (event.mouseButton() == MEvent::kMiddleMouse) 93 | { 94 | selectedMotionPathPtr = mpManager.getMotionPathPtr(0); 95 | if (selectedMotionPathPtr) 96 | { 97 | selectedMotionPathPtr->setSelectedFromTool(true); 98 | 99 | currentMode = kClickAddWorld; 100 | selectedTime = MAnimControl::currentTime().as(MTime::uiUnit()); 101 | 102 | //get closest frame to the currentTime 103 | double minTimeBoundary = 999999999; 104 | double maxTimeBoundary = 999999999; 105 | 106 | selectedMotionPathPtr->getBoundariesForTime(selectedTime, &minTimeBoundary, &maxTimeBoundary); 107 | double keyTime; 108 | if (minTimeBoundary != 999999999) 109 | keyTime = minTimeBoundary; 110 | else if (maxTimeBoundary != 999999999) 111 | keyTime = maxTimeBoundary; 112 | else 113 | keyTime = selectedTime; 114 | 115 | keyWorldPosition = selectedMotionPathPtr->getWorldPositionAtTime(keyTime); 116 | activeView.worldToView(keyWorldPosition, initialX, initialY); 117 | 118 | short int thisX, thisY; 119 | event.getPosition(thisX, thisY); 120 | 121 | MVector newPosition = contextUtils::getWorldPositionFromProjPoint(keyWorldPosition, initialX, initialY, thisX, thisY, activeView, cameraPosition); 122 | 123 | if (GlobalSettings::motionPathDrawMode == GlobalSettings::kCameraSpace) 124 | { 125 | if (!contextUtils::worldCameraSpaceToWorldSpace(newPosition, activeView, selectedTime, inverseCameraMatrix, mpManager)) 126 | return false; 127 | } 128 | 129 | mpManager.startAnimUndoRecording(); 130 | 131 | selectedMotionPathPtr->addKeyFrameAtTime(selectedTime, mpManager.getAnimCurveChangePtr(), &newPosition); 132 | 133 | activeView.refresh(); 134 | 135 | return true; 136 | } 137 | } 138 | 139 | 140 | CameraCache * cachePtr = mpManager.MotionPathManager::getCameraCachePtrFromView(activeView); 141 | int selectedCurveId; 142 | if (!old) 143 | selectedCurveId = contextUtils::processCurveHits(initialX, initialY, GlobalSettings::cameraMatrix, activeView, cachePtr, mpManager); 144 | else 145 | selectedCurveId = contextUtils::processCurveHits(activeView, cachePtr, mpManager); 146 | 147 | if (selectedCurveId != -1) 148 | { 149 | selectedMotionPathPtr = mpManager.getMotionPathPtr(selectedCurveId); 150 | if (selectedMotionPathPtr) 151 | { 152 | selectedMotionPathPtr->setSelectedFromTool(true); 153 | 154 | MIntArray ids; 155 | if (!old) 156 | contextUtils::processKeyFrameHits(initialX, initialY, selectedMotionPathPtr, activeView, GlobalSettings::cameraMatrix, cachePtr, ids); 157 | else 158 | contextUtils::processKeyFrameHits(selectedMotionPathPtr, activeView, cachePtr, ids); 159 | if (ids.length() > 0) 160 | { 161 | selectedKeyId = ids[ids.length() - 1]; 162 | 163 | keyWorldPosition = MVector::zero; 164 | selectedTime = selectedMotionPathPtr->getTimeFromKeyId(selectedKeyId); 165 | selectedMotionPathPtr->getKeyWorldPosition(selectedTime, keyWorldPosition); 166 | selectedMotionPathPtr->selectKeyAtTime(selectedTime); 167 | 168 | mpManager.startAnimUndoRecording(); 169 | 170 | if (event.isModifierControl()) 171 | { 172 | currentMode = kStroke; 173 | 174 | strokePoints.clear(); 175 | strokePoints.append(MVector(initialX, initialY, 0)); 176 | } 177 | else 178 | { 179 | currentMode = kDraw; 180 | 181 | selectedMotionPathPtr->setIsDrawing(true); 182 | selectedMotionPathPtr->setEndrawingTime(selectedTime); 183 | 184 | maxTime = MAnimControl::maxTime().as(MTime::uiUnit()); 185 | 186 | steppedTime = selectedTime; 187 | 188 | selectedMotionPathPtr->deleteAllKeyFramesAfterTime(selectedTime, mpManager.getAnimCurveChangePtr()); 189 | 190 | ////USA UN MPOINT!!! NON UN MVECTOR! 191 | 192 | MVector position = keyWorldPosition; 193 | if (GlobalSettings::motionPathDrawMode == GlobalSettings::kCameraSpace) 194 | { 195 | MPoint worldPos = position; 196 | if (!contextUtils::worldCameraSpaceToWorldSpace(worldPos, activeView, selectedTime, inverseCameraMatrix, mpManager)) 197 | return false; 198 | position = worldPos; 199 | } 200 | 201 | selectedMotionPathPtr->addKeyFrameAtTime(selectedTime, mpManager.getAnimCurveChangePtr(), &position); 202 | 203 | initialClock = clock(); 204 | } 205 | 206 | activeView.refresh(); 207 | 208 | return true; 209 | } 210 | } 211 | } 212 | else 213 | { 214 | contextUtils::refreshSelectionMethod(event, listAdjustment); 215 | 216 | if (old) 217 | fsDrawn = false; 218 | } 219 | 220 | return false; 221 | } 222 | 223 | MStatus MotionPathDrawContext::doPress(MEvent &event) 224 | { 225 | return doPressCommon(event, true) ? MStatus::kSuccess: MStatus::kFailure; 226 | } 227 | 228 | MStatus MotionPathDrawContext::doPress(MEvent & event, MHWRender::MUIDrawManager& drawMgr, const MHWRender::MFrameContext& context) 229 | { 230 | return doPressCommon(event, false) ? MStatus::kSuccess: MStatus::kFailure; 231 | } 232 | 233 | bool MotionPathDrawContext::doDragCommon(MEvent &event, const bool old) 234 | { 235 | if (selectedMotionPathPtr) 236 | { 237 | short int thisX, thisY; 238 | event.getPosition(thisX, thisY); 239 | 240 | if (currentMode == kClickAddWorld) 241 | { 242 | MVector newPosition = contextUtils::getWorldPositionFromProjPoint(keyWorldPosition, initialX, initialY, thisX, thisY, activeView, cameraPosition); 243 | if (GlobalSettings::motionPathDrawMode == GlobalSettings::kCameraSpace) 244 | { 245 | if (!contextUtils::worldCameraSpaceToWorldSpace(newPosition, activeView, selectedTime, inverseCameraMatrix, mpManager)) 246 | return false; 247 | } 248 | 249 | selectedMotionPathPtr->setFrameWorldPosition(newPosition, selectedTime, mpManager.getAnimCurveChangePtr()); 250 | } 251 | else if (currentMode == kDraw) 252 | { 253 | clock_t thisClock = clock(); 254 | 255 | double diff = thisClock - initialClock; 256 | if (diff/CLOCKS_PER_SEC > GlobalSettings::drawTimeInterval) 257 | { 258 | steppedTime += GlobalSettings::drawFrameInterval; 259 | if (steppedTime > maxTime) 260 | MGlobal::displayWarning("MotionPathDrawContext: Drawing outside of timeline frame range, not showing path, just key frames."); 261 | 262 | MVector newPosition = contextUtils::getWorldPositionFromProjPoint(keyWorldPosition, initialX, initialY, thisX, thisY, activeView, cameraPosition); 263 | if (GlobalSettings::motionPathDrawMode == GlobalSettings::kCameraSpace) 264 | { 265 | MPoint worldPos = newPosition; 266 | if (!contextUtils::worldCameraSpaceToWorldSpace(worldPos, activeView, steppedTime, inverseCameraMatrix, mpManager)) 267 | return false; 268 | newPosition = worldPos; 269 | } 270 | 271 | selectedMotionPathPtr->addKeyFrameAtTime(steppedTime, mpManager.getAnimCurveChangePtr(), &newPosition); 272 | 273 | selectedMotionPathPtr->setEndrawingTime(steppedTime); 274 | 275 | initialClock = thisClock; 276 | } 277 | } 278 | 279 | activeView.refresh(false, true); 280 | } 281 | else 282 | return false; 283 | 284 | return true; 285 | } 286 | 287 | MStatus MotionPathDrawContext::doDrag(MEvent &event) 288 | { 289 | event.getPosition( finalX, finalY ); 290 | 291 | if (selectedMotionPathPtr) 292 | { 293 | if (currentMode == kStroke) 294 | { 295 | activeView.beginXorDrawing(true, true, 2.0f, M3dView::kStippleNone); 296 | 297 | drawStroke(); 298 | 299 | MVector v(finalX, finalY, 0); 300 | if ((v - strokePoints[strokePoints.length()-1]).length() > 20) 301 | strokePoints.append(v); 302 | 303 | drawStroke(); 304 | 305 | activeView.endXorDrawing(); 306 | 307 | return MStatus::kSuccess; 308 | } 309 | else 310 | return doDragCommon(event, true) ? MStatus::kSuccess: MStatus::kFailure; 311 | } 312 | else 313 | { 314 | activeView.beginXorDrawing(); 315 | // Redraw the marquee at its old position to erase it. 316 | if (fsDrawn) 317 | contextUtils::drawMarqueeGL(initialX, initialY, finalX, finalY); 318 | 319 | fsDrawn = true; 320 | 321 | // Draw the marquee at its new position. 322 | contextUtils::drawMarqueeGL(initialX, initialY, finalX, finalY); 323 | 324 | activeView.endXorDrawing(); 325 | } 326 | return MStatus::kSuccess; 327 | } 328 | 329 | MStatus MotionPathDrawContext::doDrag(MEvent & event, MHWRender::MUIDrawManager& drawMgr, const MHWRender::MFrameContext& context) 330 | { 331 | if (selectedMotionPathPtr) 332 | { 333 | if (currentMode == kStroke) 334 | { 335 | short int thisX, thisY; 336 | event.getPosition(thisX, thisY); 337 | 338 | MVector v(thisX, thisY, 0); 339 | if ((v - strokePoints[strokePoints.length()-1]).length() > 20) 340 | strokePoints.append(v); 341 | 342 | drawStrokeNew(drawMgr); 343 | 344 | return MStatus::kSuccess; 345 | } 346 | else 347 | return doDragCommon(event, false) ? MStatus::kSuccess: MStatus::kFailure; 348 | } 349 | else 350 | { 351 | // Get the marquee's new end position. 352 | event.getPosition( finalX, finalY ); 353 | // Draw the marquee at its new position. 354 | contextUtils::drawMarquee(drawMgr, initialX, initialY, finalX, finalY); 355 | 356 | } 357 | return MStatus::kSuccess; 358 | } 359 | 360 | MVector MotionPathDrawContext::getkeyScreenPosition(const double time) 361 | { 362 | MVector pos; 363 | selectedMotionPathPtr->getKeyWorldPosition(time, pos); 364 | short thisX, thisY; 365 | activeView.worldToView(pos, thisX, thisY); 366 | return MVector(thisX, thisY, 0); 367 | } 368 | 369 | int MotionPathDrawContext::getStrokeDirection(MVector directionalVector, const MDoubleArray &keys, const int selectedIndex) 370 | { 371 | MVector pos = getkeyScreenPosition(keys[selectedIndex]); 372 | MVector pp = selectedIndex == 0 ? MVector(0,0,0): getkeyScreenPosition(keys[selectedIndex-1]) - pos; 373 | MVector ap = selectedIndex == keys.length() - 1 ? MVector(0,0,0): getkeyScreenPosition(keys[selectedIndex+1]) - pos; 374 | pp.normalize(); 375 | ap.normalize(); 376 | 377 | double dot1 = pp * directionalVector; 378 | double dot2 = ap * directionalVector; 379 | 380 | if (dot1 == 0 && dot2 < 0) 381 | return 0; 382 | 383 | if (dot2 == 0 && dot1 < 0) 384 | return 0; 385 | 386 | return dot1 > dot2 ? -1: 1; 387 | } 388 | 389 | MVector MotionPathDrawContext::getClosestPointOnPolyLine(const MVector &q) 390 | { 391 | const int count = strokePoints.length(); 392 | double finalT = 0; 393 | int index = 0; 394 | 395 | MVector b = strokePoints[0], dbq = b - q; 396 | double dist = (dbq.x*dbq.x + dbq.y*dbq.y); 397 | for (size_t i = 1; i < count; ++i) 398 | { 399 | const MVector a = b, daq = dbq; 400 | 401 | b = strokePoints[i]; 402 | dbq = b - q; 403 | 404 | const MVector dab = a - b; 405 | const double inv_sqrlen = 1./(dab.x*dab.x + dab.y*dab.y), 406 | t = (dab.x*daq.x + dab.y*daq.y) * inv_sqrlen; 407 | if (t<0.) 408 | continue; 409 | double current_dist; 410 | if (t<=1.) 411 | current_dist = (dab.x*dbq.y - dab.y*dbq.x) * (dab.x*dbq.y - dab.y*dbq.x) * inv_sqrlen; 412 | else//t>1. 413 | current_dist = (dbq.x*dbq.x + dbq.y*dbq.y); 414 | 415 | if (current_dist 1 ? 1: t; 419 | index = i; 420 | } 421 | } 422 | 423 | if (finalT == 0 && index == 0) 424 | return strokePoints[0]; 425 | else 426 | return strokePoints[index] * finalT + strokePoints[index-1] * (1-finalT); 427 | } 428 | 429 | MVector MotionPathDrawContext::getSpreadPointOnPolyLine(const int i, const int pointSize, const double strokeLenght, const std::vector &segmentLenghts) 430 | { 431 | if (i == pointSize-1) 432 | return strokePoints[strokePoints.length() - 1]; 433 | else 434 | { 435 | //we do +1 as the first key is not evaluated, and with pointSize there no -1 436 | float tl = (((float)i+1) / ((float)pointSize)) * strokeLenght; 437 | 438 | int currentSegmentIndex = 0; 439 | double currentSegmentLenght = 0; 440 | for (int j = 0; j < strokePoints.length() - 1; ++j) 441 | { 442 | if (tl > currentSegmentLenght && tl < currentSegmentLenght + segmentLenghts[j]) 443 | { 444 | currentSegmentIndex = j; 445 | break; 446 | } 447 | else 448 | currentSegmentLenght += segmentLenghts[j]; 449 | } 450 | 451 | float t = (tl - currentSegmentLenght) / (segmentLenghts[currentSegmentIndex]); 452 | return strokePoints[currentSegmentIndex+1] * t + strokePoints[currentSegmentIndex] * (1 - t); 453 | } 454 | 455 | } 456 | 457 | bool MotionPathDrawContext::doReleaseCommon(MEvent &event, const bool old) 458 | { 459 | if (selectedMotionPathPtr) 460 | { 461 | if (currentMode == kStroke) 462 | { 463 | int strokeNum = strokePoints.length() - 1; 464 | if (strokeNum > 1) 465 | { 466 | //get the direction vector 467 | MVector directionalVector; 468 | for (int i = 1; i < strokePoints.length(); ++i) 469 | { 470 | MVector pos = strokePoints[i]; 471 | directionalVector += strokePoints[i] - strokePoints[0]; 472 | } 473 | directionalVector /= strokeNum; 474 | directionalVector.normalize(); 475 | 476 | //get the key frame going into that direction, just the two left and right of this keyframe 477 | MDoubleArray keys = selectedMotionPathPtr->getKeys(); 478 | 479 | int selectedIndex = 0; 480 | for (; selectedIndex < keys.length(); ++selectedIndex) 481 | if (keys[selectedIndex] == selectedTime) 482 | break; 483 | 484 | int direction = getStrokeDirection(directionalVector, keys, selectedIndex); 485 | if (direction != 0) 486 | { 487 | // go back or forward in time until the distance of the points is not greatest from the previous distance 488 | 489 | std::vector cache, tempCache; 490 | 491 | int MAX_SKIPPED = 5, skipped = 0; 492 | 493 | MVector lastStrokePos = strokePoints[strokeNum]; 494 | double distance = (lastStrokePos - getkeyScreenPosition(keys[selectedIndex])).length(); 495 | for (int i = selectedIndex + direction; true; i += direction) 496 | { 497 | MVector pos = getkeyScreenPosition(keys[i]); 498 | double thisDistance = (lastStrokePos - pos).length(); 499 | 500 | if (thisDistance > distance) 501 | { 502 | skipped++; 503 | if (skipped > MAX_SKIPPED) 504 | break; 505 | 506 | if (i == 0 || i == keys.length() - 1) 507 | break; 508 | 509 | StrokeCache c; 510 | c.originalScreenPosition = pos; 511 | c.time = keys[i]; 512 | selectedMotionPathPtr->getKeyWorldPosition(keys[i], pos); 513 | c.originalWorldPosition = pos; 514 | tempCache.push_back(c); 515 | continue; 516 | } 517 | 518 | skipped = 0; 519 | if (tempCache.size() > 0) 520 | { 521 | cache.insert(cache.end(), tempCache.begin(), tempCache.end()); 522 | tempCache.clear(); 523 | } 524 | 525 | distance = thisDistance; 526 | 527 | StrokeCache c; 528 | c.originalScreenPosition = pos; 529 | c.time = keys[i]; 530 | selectedMotionPathPtr->getKeyWorldPosition(keys[i], pos); 531 | c.originalWorldPosition = pos; 532 | cache.push_back(c); 533 | 534 | if (i == 0 || i == keys.length() - 1) 535 | break; 536 | } 537 | 538 | int pointSize = cache.size(); 539 | if (pointSize > 0) 540 | { 541 | //we delete the key frames so maya will recalculate the tangents when adding the keyframes back 542 | for (int i = cache.size() - 1; i > -1 ; --i) 543 | selectedMotionPathPtr->deleteKeyFrameAtTime(cache[i].time, mpManager.getAnimCurveChangePtr(), false); 544 | 545 | //get the stroke lenght 546 | double strokeLenght = 0; 547 | std::vector segmentLenghts; 548 | segmentLenghts.resize(strokeNum); 549 | for (int i = 1; i < strokeNum; ++i) 550 | { 551 | segmentLenghts[i-1] = (strokePoints[i] - strokePoints[i - 1]).length(); 552 | strokeLenght += segmentLenghts[i-1]; 553 | } 554 | 555 | // match each key using the right mode (closest or spread) 556 | for (int i = 0; i < pointSize ; ++i) 557 | { 558 | if (GlobalSettings::strokeMode == 0) //closest 559 | cache[i].screenPosition = getClosestPointOnPolyLine(cache[i].originalScreenPosition); 560 | else // spread 561 | cache[i].screenPosition = getSpreadPointOnPolyLine(i, pointSize, strokeLenght, segmentLenghts); 562 | 563 | MVector newPosition = contextUtils::getWorldPositionFromProjPoint(cache[i].originalWorldPosition, cache[i].originalScreenPosition.x, cache[i].originalScreenPosition.y, cache[i].screenPosition.x, cache[i].screenPosition.y, activeView, cameraPosition); 564 | 565 | if (GlobalSettings::motionPathDrawMode == GlobalSettings::kCameraSpace) 566 | { 567 | MPoint worldPos = newPosition; 568 | if (!contextUtils::worldCameraSpaceToWorldSpace(worldPos, activeView, cache[i].time, inverseCameraMatrix, mpManager)) 569 | return false; 570 | newPosition = worldPos; 571 | } 572 | 573 | selectedMotionPathPtr->addKeyFrameAtTime(cache[i].time, mpManager.getAnimCurveChangePtr(), &newPosition, false); 574 | } 575 | } 576 | } 577 | } 578 | } 579 | 580 | if (currentMode != kNoneMode) 581 | mpManager.stopDGAndAnimUndoRecording(); 582 | 583 | selectedMotionPathPtr->deselectAllKeys(); 584 | selectedMotionPathPtr->setSelectedFromTool(false); 585 | selectedMotionPathPtr->setIsDrawing(false); 586 | 587 | activeView.refresh(); 588 | 589 | selectedMotionPathPtr = NULL; 590 | currentMode = kNoneMode; 591 | } 592 | else 593 | { 594 | event.getPosition( finalX, finalY ); 595 | 596 | if (fsDrawn && old) 597 | { 598 | activeView.beginXorDrawing(); 599 | contextUtils::drawMarqueeGL(initialX, initialY, finalX, finalY); 600 | activeView.endXorDrawing(); 601 | } 602 | 603 | contextUtils::applySelection(initialX, initialY, finalX, finalY, listAdjustment); 604 | } 605 | 606 | return 1; 607 | } 608 | 609 | MStatus MotionPathDrawContext::doRelease(MEvent &event) 610 | { 611 | return doReleaseCommon(event, true) ? MStatus::kSuccess: MStatus::kFailure; 612 | } 613 | 614 | MStatus MotionPathDrawContext::doRelease(MEvent & event, MHWRender::MUIDrawManager& drawMgr, const MHWRender::MFrameContext& context) 615 | { 616 | return doReleaseCommon(event, false) ? MStatus::kSuccess: MStatus::kFailure; 617 | } 618 | -------------------------------------------------------------------------------- /source/MotionPathEditContext.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "MotionPathEditContext.h" 3 | #include "GlobalSettings.h" 4 | #include "ContextUtils.h" 5 | 6 | extern MotionPathManager mpManager; 7 | 8 | MotionPathEditContextCmd::MotionPathEditContextCmd() 9 | {} 10 | 11 | MPxContext* MotionPathEditContextCmd::makeObj() 12 | { 13 | return new MotionPathEditContext(); 14 | } 15 | 16 | void* MotionPathEditContextCmd::creator() 17 | { 18 | return new MotionPathEditContextCmd; 19 | } 20 | 21 | MotionPathEditContext::MotionPathEditContext(): 22 | MPxContext(), 23 | ctxMenuWidget(nullptr) 24 | { 25 | this->selectedMotionPathPtr = NULL; 26 | this->currentMode = kNoneMode; 27 | 28 | setTitleString ("MotionPath Edit"); 29 | } 30 | 31 | MotionPathEditContext::~MotionPathEditContext() 32 | { 33 | if (ctxMenuWidget) 34 | { 35 | delete ctxMenuWidget; 36 | } 37 | } 38 | 39 | void MotionPathEditContext::toolOffCleanup() 40 | { 41 | M3dView view = M3dView::active3dView(); 42 | view.refresh(true, true); 43 | 44 | if (ctxMenuWidget) 45 | { 46 | delete ctxMenuWidget; 47 | ctxMenuWidget = nullptr; 48 | } 49 | 50 | for (int i = 0; i < mpManager.getMotionPathsCount(); ++i) 51 | { 52 | MotionPath *motionPath = mpManager.getMotionPathPtr(i); 53 | if (motionPath) 54 | motionPath->deselectAllKeys(); 55 | } 56 | 57 | M3dView::active3dView().refresh(true, true); 58 | 59 | MPxContext::toolOffCleanup(); 60 | } 61 | 62 | void MotionPathEditContext::toolOnSetup( MEvent& event ) 63 | { 64 | this->selectedMotionPathPtr = NULL; 65 | this->currentMode = kNoneMode; 66 | this->alongPreferredAxis = false; 67 | this->prefEditAxis = -1; 68 | this->startedRecording = false; 69 | 70 | // set the help text in the maya help boxs 71 | setHelpString("Left-Click: Select/Move; Shift+Left-Click: Add to selection; CTRL+Left-Click: Toggle selection; CTRL+Left-Click-Drag: Move Selection on the XY plane; CTRL+Middle-Click-Drag: Move Along Y Axis; Right-Click on path/frame/key: show menu"); 72 | 73 | M3dView view = M3dView::active3dView(); 74 | view.refresh(true, true); 75 | 76 | if (!ctxMenuWidget) 77 | ctxMenuWidget = new ContextMenuWidget(view.widget()); 78 | 79 | MPxContext::toolOnSetup(event); 80 | if (view.widget()) 81 | view.widget()->setFocus(); 82 | } 83 | 84 | void MotionPathEditContext::modifySelection(const MDoubleArray &selectedTimes, const bool ctrl, const bool shift) 85 | { 86 | mpManager.storePreviousKeySelection(); 87 | for (int i = 0; i < selectedTimes.length(); ++i) 88 | { 89 | bool thisShift = i != 0 || shift; 90 | 91 | if (ctrl) 92 | { 93 | if (selectedMotionPathPtr->isKeyAtTimeSelected(selectedTimes[i])) 94 | selectedMotionPathPtr->deselectKeyAtTime(selectedTimes[i]); 95 | else 96 | selectedMotionPathPtr->selectKeyAtTime(selectedTimes[i]); 97 | } 98 | else if (thisShift) 99 | { 100 | selectedMotionPathPtr->selectKeyAtTime(selectedTimes[i]); 101 | } 102 | else 103 | { 104 | if (selectedMotionPathPtr->isKeyAtTimeSelected(selectedTimes[i])) 105 | return; 106 | 107 | for (int j=0; j < mpManager.getMotionPathsCount(); ++j) 108 | mpManager.getMotionPathPtr(j)->deselectAllKeys(); 109 | selectedMotionPathPtr->selectKeyAtTime(selectedTimes[i]); 110 | } 111 | } 112 | MGlobal::executeCommand("tcMotionPathCmd -keySelectionChanged", true, true); 113 | } 114 | 115 | 116 | bool MotionPathEditContext::doPressCommon(MEvent &event, const bool old) 117 | { 118 | selectedMotionPathPtr = NULL; 119 | startedRecording = false; 120 | 121 | event.getPosition(initialX, initialY); 122 | activeView = M3dView::active3dView(); 123 | 124 | if (!GlobalSettings::showKeyFrames) 125 | return false; 126 | 127 | CameraCache * cachePtr = mpManager.MotionPathManager::getCameraCachePtrFromView(activeView); 128 | 129 | int selectedCurveId; 130 | if (!old) 131 | selectedCurveId = contextUtils::processCurveHits(initialX, initialY, GlobalSettings::cameraMatrix, activeView, cachePtr, mpManager); 132 | else 133 | selectedCurveId = contextUtils::processCurveHits(activeView, cachePtr, mpManager); 134 | 135 | if (selectedCurveId != -1) 136 | { 137 | selectedMotionPathPtr = mpManager.getMotionPathPtr(selectedCurveId); 138 | if (selectedMotionPathPtr) 139 | { 140 | MDagPath camera; 141 | activeView.getCamera(camera); 142 | MMatrix cameraMatrix = camera.inclusiveMatrix(); 143 | cameraPosition.x = cameraMatrix(3, 0); 144 | cameraPosition.y = cameraMatrix(3, 1), 145 | cameraPosition.z = cameraMatrix(3, 2); 146 | 147 | inverseCameraMatrix = cameraMatrix.inverse(); 148 | 149 | selectedMotionPathPtr->setSelectedFromTool(true); 150 | 151 | MIntArray selectedKeys; 152 | 153 | if (!old) 154 | contextUtils::processKeyFrameHits(initialX, initialY, selectedMotionPathPtr, activeView, GlobalSettings::cameraMatrix, cachePtr, selectedKeys); 155 | else 156 | contextUtils::processKeyFrameHits(selectedMotionPathPtr, activeView, cachePtr, selectedKeys); 157 | 158 | if (selectedKeys.length() == 0) 159 | { 160 | int selectedTangent = -1; 161 | if (GlobalSettings::showTangents) 162 | { 163 | int selectedKeyId; 164 | 165 | if (!old) 166 | contextUtils::processTangentHits(initialX, initialY, selectedMotionPathPtr, activeView, GlobalSettings::cameraMatrix, cachePtr, selectedKeyId, selectedTangent); 167 | else 168 | contextUtils::processTangentHits(selectedMotionPathPtr, activeView, cachePtr, selectedKeyId, selectedTangent); 169 | 170 | //move tangent 171 | if (selectedTangent != -1) 172 | { 173 | currentMode = kTangentEditMode; 174 | selectedTangentId = selectedTangent; 175 | tangentWorldPosition = MVector::zero; 176 | 177 | lastSelectedTime = selectedMotionPathPtr->getTimeFromKeyId(selectedKeyId); 178 | 179 | selectedMotionPathPtr->getTangentHandleWorldPosition(lastSelectedTime, (Keyframe::Tangent)selectedTangentId, tangentWorldPosition); 180 | lastWorldPosition = tangentWorldPosition; 181 | 182 | selectedMotionPathPtr->getKeyWorldPosition(lastSelectedTime, keyWorldPosition); 183 | } 184 | } 185 | } 186 | else 187 | { 188 | if(event.mouseButton() == MEvent::kMiddleMouse) 189 | { 190 | //move along the major axis 191 | alongPreferredAxis = true; 192 | currentMode = kFrameEditMode; 193 | prefEditAxis = event.isModifierControl() ? 1: 0; 194 | } 195 | else 196 | currentMode = kFrameEditMode; 197 | 198 | keyWorldPosition = MVector::zero; 199 | 200 | MDoubleArray times; 201 | for (int i=0; i < selectedKeys.length(); ++i) 202 | { 203 | lastSelectedTime = selectedMotionPathPtr->getTimeFromKeyId(selectedKeys[i]); 204 | times.append(lastSelectedTime); 205 | } 206 | 207 | modifySelection(times, event.isModifierControl(), event.isModifierShift()); 208 | 209 | selectedMotionPathPtr->getKeyWorldPosition(lastSelectedTime, keyWorldPosition); 210 | lastWorldPosition = keyWorldPosition; 211 | } 212 | } 213 | } 214 | else 215 | { 216 | contextUtils::refreshSelectionMethod(event, listAdjustment); 217 | 218 | if (old) 219 | fsDrawn = false; 220 | } 221 | 222 | return true; 223 | } 224 | 225 | MStatus MotionPathEditContext::doPress(MEvent &event) 226 | { 227 | return doPressCommon(event, true)? MStatus::kSuccess: MStatus::kFailure; 228 | } 229 | 230 | MStatus MotionPathEditContext::doPress(MEvent & event, MHWRender::MUIDrawManager& drawMgr, const MHWRender::MFrameContext& context) 231 | { 232 | return doPressCommon(event, false) ? MStatus::kSuccess: MStatus::kFailure; 233 | } 234 | 235 | void MotionPathEditContext::doDragCommon(MEvent &event, const bool old) 236 | { 237 | if (!startedRecording && (currentMode == kFrameEditMode || currentMode == kTangentEditMode || currentMode == kShiftKeyMode)) 238 | { 239 | mpManager.startAnimUndoRecording(); 240 | startedRecording = true; 241 | } 242 | 243 | short int thisX, thisY; 244 | event.getPosition(thisX, thisY); 245 | M3dView view = M3dView::active3dView(); 246 | 247 | if (currentMode == kFrameEditMode) 248 | { 249 | 250 | MVector newPosition = contextUtils::getWorldPositionFromProjPoint(keyWorldPosition, initialX, initialY, thisX, thisY, view, cameraPosition); 251 | 252 | //if control is pressed with find the axis with the maximum value and we move the selected keyframes only on that axis 253 | if (alongPreferredAxis) 254 | { 255 | if (prefEditAxis == 0) 256 | newPosition[1] = keyWorldPosition[1]; 257 | else 258 | { 259 | newPosition[0] = keyWorldPosition[0]; 260 | newPosition[2] = keyWorldPosition[2]; 261 | } 262 | } 263 | 264 | MVector offset = newPosition - lastWorldPosition; 265 | CameraCache * cachePtr = mpManager.MotionPathManager::getCameraCachePtrFromView(activeView); 266 | if (GlobalSettings::motionPathDrawMode == GlobalSettings::kCameraSpace) 267 | { 268 | if (!cachePtr) 269 | return; 270 | offset = offset * inverseCameraMatrix; 271 | } 272 | 273 | for (int i = 0; i < mpManager.getMotionPathsCount(); i++) 274 | { 275 | MotionPath *motionPath = mpManager.getMotionPathPtr(i); 276 | if (motionPath) 277 | { 278 | MDoubleArray selectedTimes = motionPath->getSelectedKeys(); 279 | for (int j = 0; j < selectedTimes.length(); j++) 280 | motionPath->offsetWorldPosition(GlobalSettings::motionPathDrawMode == GlobalSettings::kWorldSpace ? offset : offset * cachePtr->matrixCache[selectedTimes[j]].inverse(), selectedTimes[j], mpManager.getAnimCurveChangePtr()); 281 | } 282 | } 283 | 284 | lastWorldPosition = newPosition; 285 | } 286 | else if (currentMode == kTangentEditMode) 287 | { 288 | MVector newPosition = contextUtils::getWorldPositionFromProjPoint(tangentWorldPosition, initialX, initialY, thisX, thisY, view, cameraPosition); 289 | 290 | MMatrix toWorldMatrix; 291 | if (GlobalSettings::motionPathDrawMode == GlobalSettings::kCameraSpace) 292 | { 293 | CameraCache * cachePtr = mpManager.MotionPathManager::getCameraCachePtrFromView(activeView); 294 | if (!cachePtr) 295 | return; 296 | //newPosition = MVector(MPoint(newPosition) * inverseCameraMatrix * cachePtr->matrixCache[lastSelectedTime].inverse()); 297 | toWorldMatrix = inverseCameraMatrix * cachePtr->matrixCache[lastSelectedTime].inverse(); 298 | } 299 | else 300 | toWorldMatrix.setToIdentity(); 301 | 302 | selectedMotionPathPtr->setTangentWorldPosition(newPosition, lastSelectedTime, (Keyframe::Tangent)selectedTangentId, toWorldMatrix, mpManager.getAnimCurveChangePtr()); 303 | 304 | } 305 | 306 | view.refresh(true, true); 307 | } 308 | 309 | MStatus MotionPathEditContext::doDrag(MEvent &event) 310 | { 311 | if (selectedMotionPathPtr) 312 | { 313 | doDragCommon(event, true); 314 | } 315 | else 316 | { 317 | activeView.beginXorDrawing(); 318 | // Redraw the marquee at its old position to erase it. 319 | if (fsDrawn) 320 | contextUtils::drawMarqueeGL(initialX, initialY, finalX, finalY); 321 | 322 | fsDrawn = true; 323 | 324 | event.getPosition( finalX, finalY ); 325 | // Draw the marquee at its new position. 326 | contextUtils::drawMarqueeGL(initialX, initialY, finalX, finalY); 327 | 328 | activeView.endXorDrawing(); 329 | } 330 | 331 | return MStatus::kSuccess; 332 | } 333 | 334 | MStatus MotionPathEditContext::doDrag(MEvent & event, MHWRender::MUIDrawManager& drawMgr, const MHWRender::MFrameContext& context) 335 | { 336 | if (selectedMotionPathPtr) 337 | { 338 | doDragCommon(event, true); 339 | } 340 | else 341 | { 342 | // Get the marquee's new end position. 343 | event.getPosition( finalX, finalY ); 344 | // Draw the marquee at its new position. 345 | contextUtils::drawMarquee(drawMgr, initialX, initialY, finalX, finalY); 346 | } 347 | return MS::kSuccess; 348 | } 349 | 350 | void MotionPathEditContext::doReleaseCommon(MEvent &event, const bool old) 351 | { 352 | if (selectedMotionPathPtr) 353 | { 354 | if(startedRecording && (currentMode == kFrameEditMode || currentMode == kTangentEditMode || currentMode == kShiftKeyMode)) 355 | mpManager.stopDGAndAnimUndoRecording(); 356 | 357 | selectedMotionPathPtr->setSelectedFromTool(false); 358 | selectedMotionPathPtr = NULL; 359 | currentMode = kNoneMode; 360 | 361 | alongPreferredAxis = false; 362 | prefEditAxis = -1; 363 | 364 | M3dView view = M3dView::active3dView(); 365 | view.refresh(true, true); 366 | } 367 | else 368 | { 369 | event.getPosition( finalX, finalY ); 370 | 371 | if (fsDrawn && old) 372 | { 373 | activeView.beginXorDrawing(); 374 | contextUtils::drawMarqueeGL(initialX, initialY, finalX, finalY); 375 | activeView.endXorDrawing(); 376 | } 377 | 378 | contextUtils::applySelection(initialX, initialY, finalX, finalY, listAdjustment); 379 | } 380 | } 381 | 382 | MStatus MotionPathEditContext::doRelease(MEvent &event) 383 | { 384 | doReleaseCommon(event, true); 385 | return MStatus::kSuccess; 386 | } 387 | 388 | MStatus MotionPathEditContext::doRelease(MEvent & event, MHWRender::MUIDrawManager& drawMgr, const MHWRender::MFrameContext& context) 389 | { 390 | doReleaseCommon(event, false); 391 | return MS::kSuccess; 392 | } 393 | 394 | 395 | -------------------------------------------------------------------------------- /source/MotionPathEditContextMenuWidget.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // MotionPathEditContextMenuWidget.cpp 3 | // MotionPath 4 | // 5 | // Created by Daniele Federico on 24/01/15. 6 | // 7 | // 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include "MotionPathEditContextMenuWidget.h" 22 | #include "ContextUtils.h" 23 | #include "KeyClipboard.h" 24 | 25 | extern MotionPathManager mpManager; 26 | 27 | ContextMenuWidget::ContextMenuWidget(QWidget *parent): QWidget(parent) 28 | { 29 | m_parent = parent; 30 | this->setMouseTracking(true); 31 | m_parent->installEventFilter(this); 32 | 33 | } 34 | 35 | ContextMenuWidget::~ContextMenuWidget() 36 | { 37 | m_parent->removeEventFilter(this); 38 | } 39 | 40 | void ContextMenuWidget::refreshSelection(const QPoint point) 41 | { 42 | M3dView view = M3dView::active3dView(); 43 | curve = false; 44 | keyframe = false; 45 | frame = false; 46 | selectedKeys.clear(); 47 | 48 | QPoint p = view.widget()->mapFromGlobal(point); 49 | double y = view.widget()->height() - p.y() - 1; 50 | 51 | MString name = view.rendererString(); 52 | bool new_ = name != "hwRender_OpenGL_Renderer" && name != "base_OpenGL_Renderer"; 53 | 54 | CameraCache *cachePtr = mpManager.getCameraCachePtrFromView(view); 55 | 56 | if (new_) 57 | selectedCurveId = contextUtils::processCurveHits(p.x(), y, GlobalSettings::cameraMatrix, view, cachePtr, mpManager); 58 | else 59 | selectedCurveId = contextUtils::processCurveHits(view, cachePtr, mpManager); 60 | if (selectedCurveId == -1) 61 | return; 62 | 63 | curve = true; 64 | MotionPath *motionPathPtr = mpManager.getMotionPathPtr(selectedCurveId); 65 | if (!motionPathPtr) 66 | return; 67 | 68 | if (new_) 69 | contextUtils::processKeyFrameHits(p.x(), y, motionPathPtr, view, GlobalSettings::cameraMatrix, cachePtr, selectedKeys); 70 | else 71 | contextUtils::processKeyFrameHits(motionPathPtr, view, cachePtr, selectedKeys); 72 | if (selectedKeys.length() > 0) 73 | { 74 | keyframe = true; 75 | return; 76 | } 77 | 78 | if (new_) 79 | frame = contextUtils::processFramesHits(p.x(), y, motionPathPtr, view, GlobalSettings::cameraMatrix, cachePtr, frameTime); 80 | else 81 | frame = contextUtils::processFramesHits(motionPathPtr, view, cachePtr, frameTime); 82 | 83 | } 84 | 85 | bool ContextMenuWidget::eventFilter(QObject *o, QEvent *event) 86 | { 87 | if (event->type() == QEvent::MouseButtonPress) 88 | { 89 | QMouseEvent *pMouseEvent = static_cast(event); 90 | if((pMouseEvent->button()==Qt::RightButton)&&(pMouseEvent->modifiers()==Qt::NoModifier)) 91 | { 92 | unsigned int x = pMouseEvent->x(), y = pMouseEvent->y(); 93 | refreshSelection(pMouseEvent->globalPos()); 94 | if (!curve) 95 | return false; 96 | 97 | QPointer menu = new QMenu(); 98 | QPointer copyAction = menu->addAction("Copy Selected Keys"); 99 | 100 | QPointer pasteMenu = menu->addMenu("World Paste"); 101 | QPointer pasteAction = pasteMenu->addAction("Paste Here"); 102 | QPointer pasteAtCurrentTimeAction = pasteMenu->addAction("Paste At Current Time"); 103 | QPointer offsetPasteMenu = menu->addMenu("Offset Paste"); 104 | QPointer offsetPasteAction = offsetPasteMenu->addAction("Paste Here"); 105 | QPointer offsetPasteAtCurrentTimeAction = offsetPasteMenu->addAction("Paste At Current Time"); 106 | menu->addSeparator(); 107 | 108 | QPointer addKeyAction = menu->addAction("Add Key"); 109 | QPointer deleteKeyAction = menu->addAction("Delete Key"); 110 | QPointer deleteSelectedKeysAction = menu->addAction("Delete Selected Keys"); 111 | 112 | menu->addSeparator(); 113 | 114 | QPointer selectAllKeysAction = menu->addAction("Select All Keys"); 115 | QPointer deselectAllKeysAction = menu->addAction("Deselect All Keys"); 116 | QPointer invertKeySelectionAction = menu->addAction("Invert Key Selection"); 117 | 118 | copyAction->setData(QVariant("copy")); 119 | pasteAction->setData(QVariant("paste")); 120 | pasteAtCurrentTimeAction->setData("pasteAtCurrentTime"); 121 | addKeyAction->setData(QVariant("addKey")); 122 | deleteKeyAction->setData(QVariant("deleteKey")); 123 | offsetPasteAction->setData(QVariant("offsetPaste")); 124 | offsetPasteAtCurrentTimeAction->setData(QVariant("offsetPasteAtCurrentTime")); 125 | deleteSelectedKeysAction->setData(QVariant("deleteSelectedKeysAction")); 126 | selectAllKeysAction->setData(QVariant("selectAllKeysAction")); 127 | deselectAllKeysAction->setData(QVariant("deselectAllKeysAction")); 128 | invertKeySelectionAction->setData(QVariant("invertKeySelectionAction")); 129 | 130 | MotionPath *motionPathPtr = mpManager.getMotionPathPtr(selectedCurveId); 131 | bool keySelection = motionPathPtr->getSelectedKeys().length() > 0; 132 | bool hasCopiedKeys = KeyClipboard::getClipboard().getSize() > 0; 133 | 134 | copyAction->setEnabled(keySelection); 135 | pasteAction->setEnabled(hasCopiedKeys && (frame || keyframe)); 136 | pasteAtCurrentTimeAction->setEnabled(hasCopiedKeys); 137 | offsetPasteAction->setEnabled(hasCopiedKeys && (frame || keyframe)); 138 | offsetPasteAtCurrentTimeAction->setEnabled(hasCopiedKeys); 139 | addKeyAction->setEnabled(frame); 140 | deleteKeyAction->setEnabled(keyframe); 141 | deleteSelectedKeysAction->setEnabled(keySelection); 142 | deselectAllKeysAction->setEnabled(keySelection); 143 | 144 | menu->popup(m_parent->mapToGlobal(pMouseEvent->pos())); 145 | 146 | this->connect(menu, SIGNAL(triggered(QAction*)), this, SLOT(menuAction(QAction*))); 147 | 148 | return true; 149 | 150 | } 151 | return false; 152 | } 153 | return QWidget::eventFilter(o, event); 154 | } 155 | 156 | void ContextMenuWidget::menuAction(QAction *action) 157 | { 158 | if (action == NULL) return; 159 | 160 | MotionPath *motionPathPtr = mpManager.getMotionPathPtr(selectedCurveId); 161 | if (motionPathPtr == NULL) return; 162 | 163 | if (action->data().toString() == "copy") 164 | { 165 | motionPathPtr->storeSelectedKeysInClipboard(); 166 | return; 167 | } 168 | 169 | if (action->data().toString() == "offsetPaste") 170 | { 171 | if (motionPathPtr->getNumKeyFrames() == 0 && frameTime == MAnimControl::maxTime().as(MTime::uiUnit())) 172 | motionPathPtr->pasteKeys(MAnimControl::currentTime().as(MTime::uiUnit()), true); 173 | else 174 | motionPathPtr->pasteKeys(keyframe ? motionPathPtr->getTimeFromKeyId(selectedKeys[0]): frameTime, true); 175 | 176 | return; 177 | } 178 | 179 | if (action->data().toString() == "offsetPasteAtCurrentTime") 180 | { 181 | motionPathPtr->pasteKeys(MAnimControl::currentTime().as(MTime::uiUnit()), true); 182 | return; 183 | } 184 | 185 | if (action->data().toString() == "paste") 186 | { 187 | if (motionPathPtr->getNumKeyFrames() == 0 && frameTime == MAnimControl::maxTime().as(MTime::uiUnit())) 188 | motionPathPtr->pasteKeys(MAnimControl::currentTime().as(MTime::uiUnit()), false); 189 | else 190 | motionPathPtr->pasteKeys(keyframe ? motionPathPtr->getTimeFromKeyId(selectedKeys[0]): frameTime, false); 191 | return; 192 | } 193 | 194 | if (action->data().toString() == "pasteAtCurrentTime") 195 | { 196 | motionPathPtr->pasteKeys(MAnimControl::currentTime().as(MTime::uiUnit()), false); 197 | return; 198 | } 199 | 200 | if (action->data().toString() == "addKey" || action->data().toString() == "deleteKey") 201 | { 202 | mpManager.startAnimUndoRecording(); 203 | 204 | if (action->data().toString() == "addKey") 205 | motionPathPtr->addKeyFrameAtTime(frameTime, mpManager.getAnimCurveChangePtr()); 206 | else 207 | motionPathPtr->deleteKeyFrameWithId(selectedKeys[0], mpManager.getAnimCurveChangePtr()); 208 | 209 | mpManager.stopDGAndAnimUndoRecording(); 210 | M3dView::active3dView().refresh(); 211 | return; 212 | } 213 | 214 | if (action->data().toString() == "deleteSelectedKeysAction") 215 | { 216 | mpManager.startAnimUndoRecording(); 217 | 218 | MDoubleArray sk = motionPathPtr->getSelectedKeys(); 219 | motionPathPtr->deselectAllKeys(); 220 | for (int i = sk.length() - 1; i > -1 ; --i) 221 | motionPathPtr->deleteKeyFrameAtTime(sk[i], mpManager.getAnimCurveChangePtr()); 222 | 223 | mpManager.stopDGAndAnimUndoRecording(); 224 | M3dView::active3dView().refresh(); 225 | return; 226 | } 227 | 228 | if (action->data().toString() == "selectAllKeysAction") 229 | { 230 | mpManager.storePreviousKeySelection(); 231 | motionPathPtr->selectAllKeys(); 232 | MGlobal::executeCommand("tcMotionPathCmd -keySelectionChanged", true, true); 233 | } 234 | 235 | if (action->data().toString() == "deselectAllKeysAction") 236 | { 237 | mpManager.storePreviousKeySelection(); 238 | motionPathPtr->deselectAllKeys(); 239 | MGlobal::executeCommand("tcMotionPathCmd -keySelectionChanged", true, true); 240 | } 241 | 242 | if (action->data().toString() == "invertKeySelectionAction") 243 | { 244 | mpManager.storePreviousKeySelection(); 245 | motionPathPtr->invertKeysSelection(); 246 | MGlobal::executeCommand("tcMotionPathCmd -keySelectionChanged", true, true); 247 | } 248 | 249 | M3dView::active3dView().refresh(true, true); 250 | } 251 | 252 | -------------------------------------------------------------------------------- /source/MotionPathEditContextMenuWidgetMoc.cpp: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | ** Meta object code from reading C++ file 'MotionPathEditContextMenuWidget.h' 3 | ** 4 | ** Created by: The Qt Meta Object Compiler version 67 (Qt 5.6.1) 5 | ** 6 | ** WARNING! All changes made in this file will be lost! 7 | *****************************************************************************/ 8 | 9 | #include "../include/MotionPathEditContextMenuWidget.h" 10 | #include 11 | #include 12 | #if !defined(Q_MOC_OUTPUT_REVISION) 13 | #error "The header file 'MotionPathEditContextMenuWidget.h' doesn't include ." 14 | #elif Q_MOC_OUTPUT_REVISION != 67 15 | #error "This file was generated using the moc from 5.6.1. It" 16 | #error "cannot be used with the include files from this version of Qt." 17 | #error "(The moc has changed too much.)" 18 | #endif 19 | 20 | QT_BEGIN_MOC_NAMESPACE 21 | struct qt_meta_stringdata_ContextMenuWidget_t { 22 | QByteArrayData data[5]; 23 | char stringdata0[46]; 24 | }; 25 | #define QT_MOC_LITERAL(idx, ofs, len) \ 26 | Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \ 27 | qptrdiff(offsetof(qt_meta_stringdata_ContextMenuWidget_t, stringdata0) + ofs \ 28 | - idx * sizeof(QByteArrayData)) \ 29 | ) 30 | static const qt_meta_stringdata_ContextMenuWidget_t qt_meta_stringdata_ContextMenuWidget = { 31 | { 32 | QT_MOC_LITERAL(0, 0, 17), // "ContextMenuWidget" 33 | QT_MOC_LITERAL(1, 18, 10), // "menuAction" 34 | QT_MOC_LITERAL(2, 29, 0), // "" 35 | QT_MOC_LITERAL(3, 30, 8), // "QAction*" 36 | QT_MOC_LITERAL(4, 39, 6) // "action" 37 | 38 | }, 39 | "ContextMenuWidget\0menuAction\0\0QAction*\0" 40 | "action" 41 | }; 42 | #undef QT_MOC_LITERAL 43 | 44 | static const uint qt_meta_data_ContextMenuWidget[] = { 45 | 46 | // content: 47 | 7, // revision 48 | 0, // classname 49 | 0, 0, // classinfo 50 | 1, 14, // methods 51 | 0, 0, // properties 52 | 0, 0, // enums/sets 53 | 0, 0, // constructors 54 | 0, // flags 55 | 0, // signalCount 56 | 57 | // slots: name, argc, parameters, tag, flags 58 | 1, 1, 19, 2, 0x0a /* Public */, 59 | 60 | // slots: parameters 61 | QMetaType::Void, 0x80000000 | 3, 4, 62 | 63 | 0 // eod 64 | }; 65 | 66 | void ContextMenuWidget::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) 67 | { 68 | if (_c == QMetaObject::InvokeMetaMethod) { 69 | Q_ASSERT(staticMetaObject.cast(_o)); 70 | ContextMenuWidget *_t = static_cast(_o); 71 | Q_UNUSED(_t) 72 | switch (_id) { 73 | case 0: _t->menuAction((*reinterpret_cast< QAction*(*)>(_a[1]))); break; 74 | default: ; 75 | } 76 | } 77 | } 78 | 79 | const QMetaObject ContextMenuWidget::staticMetaObject = { 80 | { &QWidget::staticMetaObject, qt_meta_stringdata_ContextMenuWidget.data, 81 | qt_meta_data_ContextMenuWidget, qt_static_metacall, Q_NULLPTR, Q_NULLPTR} 82 | }; 83 | 84 | 85 | const QMetaObject *ContextMenuWidget::metaObject() const 86 | { 87 | return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject; 88 | } 89 | 90 | void *ContextMenuWidget::qt_metacast(const char *_clname) 91 | { 92 | if (!_clname) return Q_NULLPTR; 93 | if (!strcmp(_clname, qt_meta_stringdata_ContextMenuWidget.stringdata0)) 94 | return static_cast(const_cast< ContextMenuWidget*>(this)); 95 | return QWidget::qt_metacast(_clname); 96 | } 97 | 98 | int ContextMenuWidget::qt_metacall(QMetaObject::Call _c, int _id, void **_a) 99 | { 100 | _id = QWidget::qt_metacall(_c, _id, _a); 101 | if (_id < 0) 102 | return _id; 103 | if (_c == QMetaObject::InvokeMetaMethod) { 104 | if (_id < 1) 105 | qt_static_metacall(this, _c, _id, _a); 106 | _id -= 1; 107 | } else if (_c == QMetaObject::RegisterMethodArgumentMetaType) { 108 | if (_id < 1) 109 | *reinterpret_cast(_a[0]) = -1; 110 | _id -= 1; 111 | } 112 | return _id; 113 | } 114 | QT_END_MOC_NAMESPACE 115 | -------------------------------------------------------------------------------- /source/MotionPathOverride.cpp: -------------------------------------------------------------------------------- 1 | #include "MotionPathOverride.h" 2 | #include "MotionPathManager.h" 3 | 4 | #include 5 | 6 | extern MotionPathManager mpManager; 7 | 8 | const MString MotionPathRenderOverride::kMotionPathPassName = "tMotionPathOverride"; 9 | 10 | 11 | MotionPathRenderOverride::MotionPathRenderOverride(const MString & name) 12 | : MRenderOverride(name) 13 | , mUIName("Toolchefs MotionPath") 14 | { 15 | MHWRender::MRenderer *theRenderer = MHWRender::MRenderer::theRenderer(); 16 | if (!theRenderer) 17 | return; 18 | 19 | // Create a new set of operations as required 20 | MHWRender::MRenderer::theRenderer()->getStandardViewportOperations(mOperations); 21 | 22 | mMotionPathOp = new MotionPathUserOperation(kMotionPathPassName); 23 | 24 | mMotionPathOp->setEnabled(true); // swirl is disabled by default 25 | 26 | mOperations.insertAfter(MHWRender::MRenderOperation::kStandardSceneName, mMotionPathOp); 27 | } 28 | 29 | MotionPathRenderOverride::~MotionPathRenderOverride() 30 | { 31 | } 32 | 33 | MHWRender::DrawAPI MotionPathRenderOverride::supportedDrawAPIs() const 34 | { 35 | return MHWRender::kAllDevices; 36 | } 37 | 38 | MStatus MotionPathRenderOverride::setup(const MString & destination) 39 | { 40 | mPanelName.set(destination.asChar()); 41 | mMotionPathOp->setPanelName(mPanelName); 42 | return MRenderOverride::setup(destination); 43 | } 44 | 45 | MStatus MotionPathRenderOverride::cleanup() 46 | { 47 | return MRenderOverride::cleanup(); 48 | } 49 | 50 | 51 | MotionPathUserOperation::MotionPathUserOperation(const MString &name) 52 | : MHUDRender() 53 | { 54 | } 55 | 56 | MotionPathUserOperation::~MotionPathUserOperation() 57 | { 58 | } 59 | 60 | MStatus MotionPathUserOperation::execute(const MHWRender::MDrawContext & drawContext) 61 | { 62 | return MStatus::kSuccess; 63 | } 64 | 65 | 66 | bool MotionPathUserOperation::hasUIDrawables() const 67 | { 68 | return true; 69 | } 70 | 71 | void MotionPathUserOperation::addUIDrawables( 72 | MHWRender::MUIDrawManager& drawManager, 73 | const MHWRender::MFrameContext& frameContext) 74 | { 75 | M3dView view; 76 | if (mPanelName.length() && (M3dView::getM3dViewFromModelPanel(mPanelName, view))) 77 | { 78 | MDagPath camera; 79 | view.getCamera(camera); 80 | 81 | CameraCache* cachePtr = NULL; 82 | 83 | GlobalSettings::cameraMatrix = camera.inclusiveMatrix(); 84 | 85 | //world space mode 86 | if (GlobalSettings::motionPathDrawMode == GlobalSettings::kWorldSpace) 87 | { 88 | GlobalSettings::portWidth = view.portWidth(); 89 | GlobalSettings::portHeight = view.portHeight(); 90 | } 91 | else // camera space mode 92 | { 93 | cachePtr = mpManager.getCameraCachePtrFromView(view); 94 | if (!cachePtr) 95 | return; 96 | 97 | if (!cachePtr->isInitialized()) 98 | { 99 | cachePtr->initialize(camera.node()); 100 | cachePtr->cacheCamera(); 101 | } 102 | 103 | cachePtr->portWidth = view.portWidth(); 104 | cachePtr->portHeight = view.portHeight(); 105 | } 106 | 107 | drawManager.beginDrawInXray(); 108 | 109 | mpManager.drawBufferPaths(view, cachePtr, &drawManager, &frameContext); 110 | mpManager.drawPaths(view, cachePtr, &drawManager, &frameContext); 111 | 112 | drawManager.endDrawInXray(); 113 | } 114 | 115 | } 116 | 117 | -------------------------------------------------------------------------------- /source/PluginMain.cpp: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | MotionPath is an interactive tool to show and manipulate animation curves in maya's 3d viewport. 4 | This plugin hooks to maya's postRenderCallback in order to draw the curves in openGL. 5 | */ 6 | 7 | 8 | #include 9 | #include 10 | 11 | #include "MotionPathCmd.h" 12 | #include "MotionPathManager.h" 13 | #include "MotionPathEditContext.h" 14 | #include "MotionPathDrawContext.h" 15 | #include "MotionPathOverride.h" 16 | 17 | 18 | MotionPathManager mpManager; 19 | 20 | 21 | MStatus initializePlugin(MObject obj) 22 | { 23 | MFnPlugin plugin(obj, "ToolChefs_MotionPath", "1.0", "Any"); 24 | 25 | MStatus status = MStatus::kSuccess; 26 | 27 | if ((MGlobal::mayaState() == MGlobal::kBatch) || (MGlobal::mayaState() == MGlobal::kLibraryApp)) 28 | { 29 | MGlobal::displayInfo("Batch mode - tcMotionpath disabled"); 30 | return status; 31 | } 32 | 33 | status = plugin.registerContextCommand("tcMotionPathEditContext", MotionPathEditContextCmd::creator); 34 | if (!status) 35 | { 36 | MGlobal::displayError("Error registering tcMotionPathEditContext"); 37 | return status; 38 | } 39 | 40 | status = plugin.registerContextCommand("tcMotionPathDrawContext", MotionPathDrawContextCmd::creator); 41 | if (!status) 42 | { 43 | MGlobal::displayError("Error registering tcMotionPathDrawContext"); 44 | return status; 45 | } 46 | 47 | status = plugin.registerCommand("tcMotionPathCmd", MotionPathCmd::creator, MotionPathCmd::syntaxCreator); 48 | if (!status) 49 | { 50 | MGlobal::displayError("Error registering tcMotionPathCmd"); 51 | return status; 52 | } 53 | 54 | MHWRender::MRenderer* renderer = MHWRender::MRenderer::theRenderer(); 55 | if (renderer) 56 | { 57 | // We register with a given name 58 | MotionPathRenderOverride *overridePtr = new MotionPathRenderOverride(MOTION_PATH_RENDER_OVERRIDE_NAME); 59 | if (overridePtr) 60 | renderer->registerOverride(overridePtr); 61 | } 62 | 63 | 64 | MString addMenu; 65 | addMenu += 66 | "global proc loadTcMotionPath()\ 67 | {\ 68 | python(\"from tcMotionPath import tcMotionPath\\ntcMotionPath.run()\");\ 69 | }\ 70 | \ 71 | global proc addTcMotionPathToShelf()\ 72 | {\ 73 | global string $gShelfTopLevel;\ 74 | \ 75 | string $shelves[] = `tabLayout - q - childArray $gShelfTopLevel`;\ 76 | string $shelfName = \"\";\ 77 | int $shelfFound = 0;\ 78 | for ($shelfName in $shelves)\ 79 | {\ 80 | if ($shelfName == \"Toolchefs\")\ 81 | {\ 82 | $shelfFound = 1;\ 83 | }\ 84 | }\ 85 | if ($shelfFound == 0)\ 86 | {\ 87 | addNewShelfTab \"Toolchefs\";\ 88 | }\ 89 | \ 90 | string $buttons[] = `shelfLayout -q -childArray \"Toolchefs\"`;\ 91 | int $buttonExists = 0;\ 92 | for ($button in $buttons)\ 93 | {\ 94 | string $lab = `shelfButton - q - label $button`;\ 95 | if ($lab == \"tcMotionPath\")\ 96 | {\ 97 | $buttonExists = 1;\ 98 | break;\ 99 | }\ 100 | }\ 101 | \ 102 | if ($buttonExists == 0)\ 103 | {\ 104 | string $myButton = `shelfButton\ 105 | - parent Toolchefs\ 106 | - enable 1\ 107 | - width 34\ 108 | - height 34\ 109 | - manage 1\ 110 | - visible 1\ 111 | - annotation \"Load tcMotionPath\"\ 112 | - label \"tcMotionPath\"\ 113 | - image1 \"tcMotionPath.png\"\ 114 | - style \"iconOnly\"\ 115 | - sourceType \"python\"\ 116 | - command \"from tcMotionPath import tcMotionPath\\ntcMotionPath.run()\"`;\ 117 | }\ 118 | }\ 119 | global proc addTcMotionPathToMenu()\ 120 | {\ 121 | global string $gMainWindow;\ 122 | global string $showToolochefsMenuCtrl;\ 123 | if (!(`menu - exists $showToolochefsMenuCtrl`))\ 124 | {\ 125 | string $name = \"Toolchefs\";\ 126 | $showToolochefsMenuCtrl = `menu -p $gMainWindow -to true -l $name`;\ 127 | string $tcToolsMenu = `menuItem -subMenu true -label \"Tools\" -p $showToolochefsMenuCtrl \"tcToolsMenu\"`;\ 128 | menuItem -label \"Load tcMotionPath\" -p $tcToolsMenu -c \"loadTcMotionPath\" \"tcActiveMotionPathItem\";\ 129 | }\ 130 | else\ 131 | {\ 132 | int $deformerMenuExist = false;\ 133 | string $defMenu = \"\";\ 134 | string $subitems[] = `menu -q -itemArray $showToolochefsMenuCtrl`;\ 135 | for ($item in $subitems)\ 136 | {\ 137 | if ($item == \"tcToolsMenu\")\ 138 | {\ 139 | $deformerMenuExist = true;\ 140 | $defMenu = $item;\ 141 | break;\ 142 | }\ 143 | }\ 144 | if (!($deformerMenuExist))\ 145 | {\ 146 | string $tcToolsMenu = `menuItem -subMenu true -label \"Tools\" -p $showToolochefsMenuCtrl \"tcToolsMenu\"`;\ 147 | menuItem -label \"Load tcMotionPath\" -p $tcToolsMenu -c \"loadTcMotionPath\" \"tcActiveMotionPathItem\";\ 148 | }\ 149 | else\ 150 | {\ 151 | string $subitems2[] = `menu -q -itemArray \"tcToolsMenu\"`;\ 152 | int $deformerExists = 0;\ 153 | for ($item in $subitems2)\ 154 | {\ 155 | if ($item == \"tcActiveMotionPathItem\")\ 156 | {\ 157 | $deformerExists = true;\ 158 | break;\ 159 | }\ 160 | }\ 161 | if (!$deformerExists)\ 162 | {\ 163 | menuItem -label \"Load tcMotionPath\" -p $defMenu -c \"loadTcMotionPath\" \"tcActiveMotionPathItem\";\ 164 | }\ 165 | }\ 166 | }\ 167 | };addTcMotionPathToMenu();addTcMotionPathToShelf();"; 168 | MGlobal::executeCommand(addMenu, false, false); 169 | 170 | return status; 171 | } 172 | 173 | MStatus uninitializePlugin(MObject obj) 174 | { 175 | MStatus status; 176 | MFnPlugin plugin(obj); 177 | 178 | if ((MGlobal::mayaState() == MGlobal::kBatch) || (MGlobal::mayaState() == MGlobal::kLibraryApp)) 179 | { 180 | MGlobal::displayInfo("Batch mode - tcMotionpath disabled"); 181 | return status; 182 | } 183 | 184 | mpManager.cleanupViewports(); 185 | mpManager.removeCallbacks(); 186 | 187 | status = plugin.deregisterContextCommand("tcMotionPathEditContext"); 188 | if (!status) 189 | { 190 | MGlobal::displayError("Error deregistering tcMotionPathEditContext"); 191 | return status; 192 | } 193 | 194 | status = plugin.deregisterContextCommand("tcMotionPathDrawContext"); 195 | if (!status) 196 | { 197 | MGlobal::displayError("Error deregistering tcMotionPathDrawContext"); 198 | return status; 199 | } 200 | 201 | status = plugin.deregisterCommand("tcMotionPathCmd"); 202 | if (!status) 203 | { 204 | MGlobal::displayError("Error deregistering tcMotionPathCmd"); 205 | return status; 206 | } 207 | 208 | MHWRender::MRenderer* renderer = MHWRender::MRenderer::theRenderer(); 209 | if (renderer) 210 | { 211 | // Find override with the given name and deregister 212 | const MHWRender::MRenderOverride* overridePtr = renderer->findRenderOverride(MOTION_PATH_RENDER_OVERRIDE_NAME); 213 | if (overridePtr) 214 | { 215 | renderer->deregisterOverride(overridePtr); 216 | delete overridePtr; 217 | } 218 | } 219 | 220 | return status; 221 | } 222 | -------------------------------------------------------------------------------- /source/Vp2DrawUtils.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // VP2DrawUtils.cpp 3 | // MotionPath 4 | // 5 | // Created by Daniele Federico on 16/11/14. 6 | // 7 | // 8 | 9 | #include "Vp2DrawUtils.h" 10 | #include 11 | 12 | #define PI 3.1415 13 | 14 | void VP2DrawUtils::drawLineStipple(const MVector &origin, const MVector &target, float lineWidth, const MColor &color, const MMatrix &cameraMatrix, MHWRender::MUIDrawManager* drawManager, const MHWRender::MFrameContext* frameContext) 15 | { 16 | MVector zVec(cameraMatrix[2][0], cameraMatrix[2][1], cameraMatrix[2][2]); 17 | MVector cPos(cameraMatrix[3][0], cameraMatrix[3][1], cameraMatrix[3][2]); 18 | if ((cPos - origin) * zVec <= 0.0001) 19 | return; 20 | 21 | drawManager->setColor(color); 22 | drawManager->setLineWidth(lineWidth); 23 | drawManager->setPaintStyle(MHWRender::MUIDrawManager::kStippled); 24 | drawManager->setLineStyle(8, 0xAAAA); 25 | double x1, y1, x2, y2; 26 | frameContext->worldToViewport(origin, x1, y1); 27 | frameContext->worldToViewport(target, x2, y2); 28 | drawManager->line2d(MPoint(x1, y1), MPoint(x2, y2)); 29 | } 30 | 31 | 32 | void VP2DrawUtils::drawLine(const MVector &origin, const MVector &target, float lineWidth, const MMatrix &cameraMatrix, MHWRender::MUIDrawManager* drawManager, const MHWRender::MFrameContext* frameContext) 33 | { 34 | MVector zVec(cameraMatrix[2][0], cameraMatrix[2][1], cameraMatrix[2][2]); 35 | MVector cPos(cameraMatrix[3][0], cameraMatrix[3][1], cameraMatrix[3][2]); 36 | if ((cPos - origin) * zVec <= 0.0001) 37 | return; 38 | 39 | drawManager->setLineWidth(lineWidth); 40 | double x1, y1, x2, y2; 41 | frameContext->worldToViewport(origin, x1, y1); 42 | frameContext->worldToViewport(target, x2, y2); 43 | drawManager->line2d(MPoint(x1, y1), MPoint(x2, y2)); 44 | } 45 | 46 | 47 | void VP2DrawUtils::drawLineWithColor(const MVector &origin, const MVector &target, float lineWidth, const MColor &color, const MMatrix &cameraMatrix, MHWRender::MUIDrawManager* drawManager, const MHWRender::MFrameContext* frameContext) 48 | { 49 | drawManager->setColor(color); 50 | VP2DrawUtils::drawLine(origin, target, lineWidth, cameraMatrix, drawManager, frameContext); 51 | } 52 | 53 | 54 | void VP2DrawUtils::drawPoint(const MVector &point, float size, const MMatrix &cameraMatrix, MHWRender::MUIDrawManager* drawManager, const MHWRender::MFrameContext* frameContext) 55 | { 56 | MVector zVec(cameraMatrix[2][0], cameraMatrix[2][1], cameraMatrix[2][2]); 57 | MVector cPos(cameraMatrix[3][0], cameraMatrix[3][1], cameraMatrix[3][2]); 58 | if ((cPos - point) * zVec <= 0.0001) 59 | return; 60 | 61 | double x, y; 62 | frameContext->worldToViewport(point, x, y); 63 | drawManager->circle2d(MPoint(x, y), size / 2, true); 64 | } 65 | 66 | 67 | void VP2DrawUtils::drawPointWithColor(const MVector &point, float size, const MColor &color, const MMatrix &cameraMatrix, MHWRender::MUIDrawManager* drawManager, const MHWRender::MFrameContext* frameContext) 68 | { 69 | drawManager->setColor(color); 70 | VP2DrawUtils::drawPoint(point, size, cameraMatrix, drawManager, frameContext); 71 | } 72 | 73 | void VP2DrawUtils::drawKeyFrames(std::vector keys, const float size, const double colorMultiplier, const int portWidth, const int portHeight, const bool showRotationKeyframes, const MMatrix &cameraMatrix, MHWRender::MUIDrawManager* drawManager, const MHWRender::MFrameContext* frameContext) 74 | { 75 | for (unsigned int ki = 0; ki < keys.size(); ++ki) 76 | { 77 | Keyframe* key = keys[ki]; 78 | if (!key) 79 | continue; 80 | 81 | std::vector tAxis, rAxis; 82 | key->getKeyTranslateAxis(tAxis); 83 | //std::cout << key->time << std::endl; 84 | if (tAxis.size() < 1) 85 | { 86 | //std::cout << "axis 0 " << key->time << std::endl; 87 | continue; 88 | } 89 | if (showRotationKeyframes) 90 | key->getKeyRotateAxis(rAxis); 91 | 92 | double blackBackgroundFactor = 1.2; 93 | MColor color(0.0, 0.0, 0.0); 94 | double centerX, centerY; 95 | frameContext->worldToViewport(key->worldPosition, centerX, centerY); 96 | 97 | drawManager->setColor(color); 98 | drawManager->circle2d(MPoint(centerX, centerY), size * blackBackgroundFactor / 2, true); 99 | 100 | if (key->selectedFromTool) 101 | { 102 | MColor color(1.0, 1.0, 1.0); 103 | drawManager->setColor(color); 104 | drawManager->circle2d(MPoint(centerX, centerY), size / 2, true); 105 | } 106 | else 107 | { 108 | double stepSize = size / 2 / tAxis.size(); 109 | for (int i = 0; i < tAxis.size(); ++i) 110 | { 111 | Keyframe::getColorForAxis(tAxis[i], color); 112 | color *= colorMultiplier; 113 | 114 | drawManager->setColor(color); 115 | drawManager->circle2d(MPoint(centerX, centerY), stepSize * (tAxis.size() - i), true); 116 | } 117 | 118 | /* 119 | int nSections = 3; 120 | int step = nSections / tAxis.size(); 121 | int currentStep = 0; 122 | //std::cout << "triangle 1" << std::endl; 123 | Keyframe::getColorForAxis(tAxis[currentStep], color); 124 | color *= colorMultiplier; 125 | 126 | double angleAdd = (2.0 * double(PI) / double(nSections)); 127 | double angle = -PI / 2; 128 | 129 | double x1 = 0, y1 = -1, x2, y2; 130 | for (int i = 0; i < nSections; ++i) 131 | { 132 | //std::cout << i << std::endl; 133 | if (i / step > currentStep) 134 | { 135 | currentStep = i / step; 136 | if (currentStep == tAxis.size()) currentStep = 0; 137 | Keyframe::getColorForAxis(tAxis[currentStep], color); 138 | color *= colorMultiplier; 139 | } 140 | 141 | angle -= angleAdd; 142 | x2 = size * 0.5 * sin(angle); 143 | y2 = size * 0.5 * cos(angle); 144 | 145 | MPointArray points; 146 | points.append(MPoint(centerX, centerY)); 147 | points.append(MPoint(centerX + x1, centerY + y1)); 148 | points.append(MPoint(centerX + x2, centerY + y2)); 149 | 150 | drawManager->setColor(color); 151 | drawManager->mesh2d(MHWRender::MUIDrawManager::kTriangles, points); 152 | //drawManager->arc2d(MPoint(centerX, centerY), MVector(x1, y1), MVector(x2, y2), size / 2, true); 153 | x1 = x2; 154 | y1 = y2; 155 | } 156 | */ 157 | 158 | } 159 | 160 | if (rAxis.size() > 0) 161 | { 162 | double lineWidth = size / 5; 163 | if (lineWidth < 1) lineWidth = 1; 164 | 165 | double unit = size * blackBackgroundFactor / 2; 166 | float x1s[3] = { -unit * 0.8, unit * 1.5, unit * -1.5 }; 167 | float y1s[3] = { unit * 1.2, unit * 0.1, unit * 0.1 }; 168 | 169 | float x2s[3] = { unit * 0.8, unit * 0.7, unit * -0.7 }; 170 | float y2s[3] = { unit * 1.2, unit * -1.2, unit * -1.2 }; 171 | 172 | MColor color; 173 | MVector p1(0, 0, 0), p2(0, 0, 0); 174 | for (unsigned int i = 0; i < rAxis.size(); ++i) 175 | { 176 | Keyframe::getColorForAxis(rAxis[i], color); 177 | color *= colorMultiplier; 178 | 179 | p1.x = centerX + x1s[i]; 180 | p1.y = centerY + y1s[i]; 181 | 182 | p2.x = centerX + x2s[i]; 183 | p2.y = centerY + y2s[i]; 184 | 185 | drawManager->setColor(color); 186 | drawManager->setLineWidth(lineWidth); 187 | drawManager->line2d(p1, p2); 188 | } 189 | } 190 | } 191 | } 192 | 193 | void VP2DrawUtils::drawKeyFramePoints(KeyframeMap &keyframesCache, const float size, const double colorMultiplier, const int portWidth, const int portHeight, const bool showRotationKeyframes, const MMatrix &cameraMatrix, MHWRender::MUIDrawManager* drawManager, const MHWRender::MFrameContext* frameContext) 194 | { 195 | std::vector keys; 196 | keys.reserve(keyframesCache.size()); 197 | 198 | for (KeyframeMapIterator keyIt = keyframesCache.begin(); keyIt != keyframesCache.end(); keyIt++) 199 | { 200 | Keyframe* key = &keyIt->second; 201 | if (!key) 202 | continue; 203 | MVector zVec(cameraMatrix[2][0], cameraMatrix[2][1], cameraMatrix[2][2]); 204 | MVector cPos(cameraMatrix[3][0], cameraMatrix[3][1], cameraMatrix[3][2]); 205 | if ((cPos - key->worldPosition) * zVec <= 0.0001) 206 | continue; 207 | keys.push_back(key); 208 | } 209 | 210 | drawKeyFrames(keys, size, colorMultiplier, portWidth, portHeight, showRotationKeyframes, cameraMatrix, drawManager, frameContext); 211 | } 212 | 213 | void VP2DrawUtils::convertWorldSpaceToCameraSpace(CameraCache* cachePtr, std::map &positions, std::map &screenSpacePositions, MHWRender::MUIDrawManager* drawManager, const MHWRender::MFrameContext* frameContext) 214 | { 215 | 216 | } 217 | 218 | void VP2DrawUtils::drawFrameLabel(double frame, const MVector &framePos, M3dView &view, const double sizeOffset, const MColor &color, const MMatrix &cameraMatrix, MHWRender::MUIDrawManager* drawManager, const MHWRender::MFrameContext* frameContext) 219 | { 220 | MVector zVec(cameraMatrix[2][0], cameraMatrix[2][1], cameraMatrix[2][2]); 221 | MVector cPos(cameraMatrix[3][0], cameraMatrix[3][1], cameraMatrix[3][2]); 222 | if ((cPos - framePos) * zVec <= 0.0001) 223 | return; 224 | 225 | drawManager->setFontSize(MHWRender::MUIDrawManager::kDefaultFontSize); 226 | drawManager->setColor(color); 227 | 228 | double viewX, viewY; 229 | frameContext->worldToViewport(framePos, viewX, viewY); 230 | 231 | MString frameStr; 232 | frameStr = frame; 233 | 234 | drawManager->text(MPoint(viewX, viewY + (GlobalSettings::frameSize * sizeOffset)), frameStr, MHWRender::MUIDrawManager::kCenter); 235 | } 236 | 237 | -------------------------------------------------------------------------------- /source/animCurveUtils.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // animCurveUtils.cpp 3 | // MotionPath 4 | // 5 | // Created by Daniele Federico on 15/06/15. 6 | // 7 | // 8 | 9 | #include "animCurveUtils.h" 10 | 11 | 12 | bool animCurveUtils::updateCurve(const MPlug &plug, MFnAnimCurve &curve, const MTime ¤tTime, double &oldValue, double &newValue, int &newKeyId, int &oldKeyId) 13 | { 14 | curve.evaluate(currentTime, oldValue); 15 | newValue = plug.asDouble(); 16 | 17 | newKeyId = -1; 18 | if(newValue != oldValue) 19 | { 20 | unsigned int id; 21 | if(curve.find(currentTime, id)) 22 | { 23 | curve.setValue(id, newValue); 24 | oldKeyId = id; 25 | } 26 | else 27 | newKeyId = curve.addKeyframe(currentTime, newValue); 28 | 29 | return true; 30 | } 31 | 32 | return false; 33 | } 34 | 35 | void animCurveUtils::restoreCurve(MFnAnimCurve &curve, const MTime ¤tTime, const double oldValue, const int newKeyId, const int oldKeyId) 36 | { 37 | if(newKeyId > -1) 38 | { 39 | unsigned int id; 40 | curve.find(currentTime, id); 41 | curve.remove(id); 42 | } 43 | else 44 | curve.setValue(oldKeyId, oldValue); 45 | } 46 | 47 | --------------------------------------------------------------------------------