#ifndef shaveCursorCtx_h #define shaveCursorCtx_h // Shave and a Haircut // (c) 2019 Epic Games // US Patent 6720962 //Qt headers must be included before any others !!! #include #include #include #include #if QT_VERSION < 0x050000 # include # include #else # include # include #endif #include #include #include #include #include #include #include #include #include #include "shaveHairShape.h" #include "shaveSDKTYPES.h" #if MAYA_API_VERSION < 20180000 class MEvent; #endif class shaveBrushManip; class shaveCursorCtx; //Qt mouse test -- vlad|17Mar2010 class shaveQtMouseWatcher : public QObject { public: shaveQtMouseWatcher(shaveCursorCtx* ctx) { m_ctx = ctx; m_busy = false; } virtual ~shaveQtMouseWatcher(){} static bool IsBusy() {return m_busy;} protected: bool eventFilter(QObject* obj, QEvent* event); private: shaveCursorCtx* m_ctx; static bool m_busy; }; void CheckGlobalQtViewport20Tracker(); class globalQtViewport20Tracker : public QObject { public: globalQtViewport20Tracker(){} virtual ~globalQtViewport20Tracker(){} protected: bool eventFilter(QObject* obj, QEvent* event); MMatrix worldToCam; }; //#define GLOBAL_FALLBACK #ifdef GLOBAL_FALLBACK void CheckAndSetGlobalQtWatcher(); void SetEventsHappen(); bool GetEventsHappen(); void ClearEvents(); bool IsMouseDown(); bool IsToolActive(); class globalQtMouseWatcher : public QObject { public: globalQtMouseWatcher(){} virtual ~globalQtMouseWatcher(){} protected: bool eventFilter(QObject* obj, QEvent* event); }; void StartQTimer(); QElapsedTimer& GetQTimer(); qint64 GetLastMoveTime(); void SetLastMoveTime(qint64 t); #endif class NotBusyEvent : public QEvent { public: enum {aType = 4500}; NotBusyEvent():QEvent((QEvent::Type)aType){}; }; //LARGE_INTEGER GetLastMoveTime(); class shaveCursorCtx : public MPxContext { friend class shaveQtMouseWatcher; public: shaveCursorCtx(); virtual ~shaveCursorCtx(); virtual void deleteAction() {} void enableFalloff(bool enable) { mFalloffEnabled = enable; } float getBrushSize() const { return mBrushSize; } float getBrushStren() const { return mBrushStren; } virtual void getClassName(MString& name) const = 0; bool isFalloffEnabled() const { return mFalloffEnabled; } bool isResizing() const { return mIsResizing; } void resizeKeyPressed(bool isPressed); void setBrushSize(float size); void setBrushStren(float stren) { mBrushStren = stren; } // // 'screenPos' is normalized to the range 0.0 to 1.0 for both view // dimensions. Thus (0, 0) is the lower left corner of the view and // (1, 1) is the upper right. // // If a derived class is only interested in mouse clicks, not strokes, // then it should perform its click operation in this method and then // return MS::kEndOfFile to indicate that the remainder of the stroke // can be ignored. Otherwise it should return MS::kSuccess on success // or any of the other failure codes for failure. // virtual MStatus strokeBegin( VERT& eyePoint, VERT& viewDir, VERT& upDir, VERT& screenPos, VERT& worldPos ) { return MS::kSuccess; } // // 'screenPos' and 'screenDelta' are normalized to the range 0.0 to 1.0 // for both view dimensions. Thus (0, 0) is the lower left corner of // the view and (1, 1) is the upper right. If the drag extends beyond // the edges of the view then the values passed in may lie outside that // range. // // Derived classes are guaranteed that the position of the cursor in // the final strokeDrag() will be identical to that when strokeEnd() is // called. // virtual MStatus strokeDrag( VERT& screenPos, VERT& worldPos, VERT& screenDelta, VERT& worldDelta ) { return MS::kSuccess; } virtual MStatus strokeEnd() { return MS::kSuccess; } protected: typedef enum { kMouseMoved, kMouseLeftWindow } MouseEventType; typedef struct { MouseEventType type; MNativeWindowHdl window; int x; int y; } EventData; // // Internal Methods // static void activeViewChanged(void* clientData); void catchActiveViewEvents(); void cleanupStroke(); static shaveCursorCtx* getActiveCtx() { return mActiveCtx; } MPoint getWorldPt( const M3dView& view, short viewX, short viewY ) const; void hideHair(); void leaveWindow(MNativeWindowHdl window, int x, int y); void pointerMoved(MNativeWindowHdl window, int x, int y); void motionEventHandler(EventData* event); void uncatchActiveViewEvents(); void unhideHair(); #if defined _WIN32 static LRESULT CALLBACK WinEventHandler(int nCode, WPARAM wParam, LPARAM lParam); #elif defined LINUX static void XEventHandler( Widget widget, XtPointer clientData, XEvent* event, Boolean* continueDispatch ); #elif defined OSMac_ //Qt stuff should be used #endif static shaveCursorCtx* mActiveCtx; MCallbackId mActiveViewChangedId; float mBrushSize; float mBrushStren; double mCentroidFraction; bool mDoingStroke; static MCursor mDoubleArrowCursor; MNativeWindowHdl mEventWindow; bool mFalloffEnabled; bool mFastBrush; MDagPathArray mHiddenHairNodes; bool mIsActive; bool mIsResizing; shaveBrushManip* mManip; MDagPath mProxyPath; bool mResizeKeyPressed; short mStrokeLastX; short mStrokeLastY; float mStrokeStartBrushSize; VERT mStrokeStartWorld; short mStrokeStartX; short mStrokeStartY; shaveHairShape::HairDisplayMode mTargetDisplayMode; shaveHairShape* mTargetShape; #ifdef _WIN32 HHOOK mMouseHookId; bool mTrackingLeaveWindow; #endif private: virtual MStatus doPress (MEvent& event, MHWRender::MUIDrawManager& drawMgr, const MHWRender::MFrameContext& context){ return doPress(event);} virtual MStatus doDrag (MEvent& event, MHWRender::MUIDrawManager& drawMgr, const MHWRender::MFrameContext& context){ return doDrag(event);} virtual MStatus doRelease (MEvent& event, MHWRender::MUIDrawManager& drawMgr, const MHWRender::MFrameContext& context){ return doRelease(event);} virtual MStatus doDrag(MEvent& event); virtual MStatus doPress(MEvent& event); virtual MStatus doRelease(MEvent& event); virtual void toolOffCleanup(); virtual void toolOnSetup(MEvent& event); }; #endif