#ifndef _shaveUtil_h #define _shaveUtil_h // Shave and a Haircut // (c) 2019 Epic Games // US Patent 6720962 #include #include #include #include #include #include #include #include #include #include #include #include "shaveSDKTYPES.h" #if MAYA_API_VERSION < 20180000 class MFloatPointArray; class MSelectionList; #endif class shaveHairShape; class shaveRenderer; class shaveUtil { public: static void buildLightList(); static void classifyShaveNodes( const MObjectArray& shaveNodes, bool& haveHair, bool& haveInstances ); // Compare two Shave version strings of the form 1.2.3 or 1.2v3 // Returns -1 if v1 < v2, 0 if v1 == v2, +1 if v1 > v2. static int compareShaveVersions(MString v1, MString v2); // Returns true if it made changes to the selection list. static bool convertComponentSelections( bool* pHiliteListChanged = NULL ); static MString expandStatFileName(MString fileName); static MString expandTempFileName(MString fileName); // Copy one full line of input to the output, returning to the caller // as much as will fit in the supplied buffer. // // Returns false if there was no input left to read. static bool fileCopyLine( FILE* input, FILE* output, char* buffer, unsigned int bufferSize ); static void fileDelete(MString fileName); static bool fileExists(MString fileName); static bool fileRename(MString oldName, MString newName); static MStatus forceCompute(MObject shaveNode); static void forceComputeAll(); static MString formatFrame(float frame); // Returns the value of a plug of type kAddr. static void* getAddrPlugValue(const MPlug& addrPlug, MStatus* st = NULL); static MDagPath getCurrentHairShape(bool* pIsHilited = NULL); // Displacements are applied in worldSpace so the returned vert // positions will be in worldSpace. static void getDisplacedMeshVertices( MObject mesh, MObject shadingGroup, MFloatPointArray& displacedVerts ); static void getDisplayNodes(MObjectArray& nodes); static const MDagPathArray& getFields(); static int getLightIndex(const void* lightBlindData); static int getLightIndex( const MFloatVector& point, const MFloatVector& dirToLight ); static int getLightIndexFromID(int id); static int getLoadDepth(); static shaveHairShape* getLoadedHairShape(); static MObject getMesh( MDagPath& path, int uTess = -1, int vTess = -1, int sDept = 1, int sSamp = 1, bool includeDisplacements = false ); static MObject getNode(MString nodeName); static void getNodesByTypeId(MTypeId nodeType, MObjectArray& nodes); static void getPathsByTypeId(MTypeId nodeType, MDagPathArray& nodes); static long getpid(); static void getShadingGroups( const MDagPath& path, MObjectArray& shadingGroups ); static void getShaveGlobalsNodes(MObjectArray& nodes); static void getShaveNodes(MDagPathArray& nodes); static void getShaveNodes(MObjectArray& nodes); static void getSubdQuads( MDagPath& subdPath, MUint64Array& quadIDs, MPointArray& verts, MIntArray& vertIndices, MDoubleArray* vertUs = NULL, MDoubleArray* vertVs = NULL ); static void getSubdQuads( MObject subdData, MUint64Array& quadIDs, MPointArray& verts, MIntArray& vertIndices, MDoubleArray* vertUs = NULL, MDoubleArray* vertVs = NULL ); static unsigned getThreadSettings( unsigned numItems, unsigned* pItemsPerThread = NULL ); static MString getHostName(); static bool isIgnoringNextSelectionChange(); static bool isLoadingFile(); static bool isSurfaceDisplaced(const MDagPath& surface); static MString makeStatFileName(MString nodeName, float frame); static MString makeTempStatFileName( MString nodeName, MString suffix, float frame ); // If 'path' is empty then the default temp directory will be used. // Not thread-safe! static MString makeUniqueTempFileName( MString directory, MString prefix, MString suffix ); static int reorderInt(int val); static MStatus sampleCurves( const MObjectArray& curves, unsigned int samplesPerCurve, WFTYPE& sampleData ); static void setFieldsDirty() { mFieldsDirty = true; } static void setFrame(float newFrame); static void setIgnoringNextSelectionChange(bool ignoreIt); static void setLoadingFile(bool newState); static void setWFTYPEVelocities(WFTYPE* wf1, WFTYPE* wf2); static void splitFileName( MString fileName, MString& baseName, MString& extension ); static bool splitShaveVersion( const MString version, int versionParts[3] ); static MString substituteAll( const MString& str, char oldChar, char newChar ); static MString substituteAll( const MString& str, const MString& oldSubstr, const MString& newSubstr ); static void timestamp(const MString& msg); protected: static void appendConnectedShadingGroups( const MPlug& plug, MObjectArray& shadingGroups ); static MDagPath getFirstHairShape(MSelectionList& list); public: typedef struct { MDagPath path; int minId; int maxId; void* blindData; } LightInfo; static std::vector globalLightList; private: static MDagPathArray mFields; static bool mFieldsDirty; static bool mIgnoreNextSelectionChange; static int mLoadDepth; }; inline int shaveUtil::getLoadDepth() { return mLoadDepth; } inline bool shaveUtil::isIgnoringNextSelectionChange() { return mIgnoreNextSelectionChange; } inline bool shaveUtil::isLoadingFile() { return (mLoadDepth > 0); } inline void shaveUtil::setIgnoringNextSelectionChange(bool ignoreIt) { mIgnoreNextSelectionChange = ignoreIt; } #endif