// Shave and a Haircut // (c) 2019 Epic Games // US Patent 6720962 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "shaveConstant.h" #include "shaveError.h" #include "shaveGlobals.h" #include "shaveHairShape.h" #include "shaveRender.h" #include "shaveSDK.h" #include "shaveUtil.h" #include MTypeId shaveGlobals::id(0x00106501); const MString shaveGlobals::defaultNodeName("shaveGlobals"); const MString shaveGlobals::nodeTypeName("shaveGlobals"); const int shaveGlobals::kNodeVersion = 11; // Attribute Objects MObject shaveGlobals::aAddress; MObject shaveGlobals::aGlInst; MObject shaveGlobals::aComposite2d; MObject shaveGlobals::aDisplayGuides; MObject shaveGlobals::aDisplayGuideThick; MObject shaveGlobals::aDisplaySegmentLimit; MObject shaveGlobals::aDoCompositing; MObject shaveGlobals::aDoHairShadows; MObject shaveGlobals::aEnableInstanceGeometry; MObject shaveGlobals::aGravity; MObject shaveGlobals::aHairFilename; MObject shaveGlobals::aHairOcclusionObjects; MObject shaveGlobals::aHideHair; MObject shaveGlobals::aInfo1; MObject shaveGlobals::aInfo2; MObject shaveGlobals::aKeepHairRenderFiles; MObject shaveGlobals::aLiveMode; MObject shaveGlobals::aLiveModeRecord; MObject shaveGlobals::aLiveModePlayback; MObject shaveGlobals::aMaxThreads; MObject shaveGlobals::aNativeIllumination; MObject shaveGlobals::aNodeVersion; MObject shaveGlobals::aNormalRenderMode; MObject shaveGlobals::aPrimCameraVis; MObject shaveGlobals::aPrimGiVis; MObject shaveGlobals::aPrimLightVis; MObject shaveGlobals::aRenderQuality; MObject shaveGlobals::aShadowDensity; MObject shaveGlobals::aShadowMatte; MObject shaveGlobals::aShadowMatteIncludeBackfacing; MObject shaveGlobals::aStatFileDir; MObject shaveGlobals::aThreadPerProcessor; MObject shaveGlobals::aTileMemoryLimit; MObject shaveGlobals::aTransparencyDepth; MObject shaveGlobals::aUseAllLights; MObject shaveGlobals::aUseDRA; MObject shaveGlobals::aVisibleInReflections; MObject shaveGlobals::aVerbose; MObject shaveGlobals::aVoxelResolution; MObject shaveGlobals::aVoxelScaling; // Renderman defaults MObject shaveGlobals::aRibBinary; MObject shaveGlobals::aRibBlurEnable; MObject shaveGlobals::aRibBlurInheritSettings; MObject shaveGlobals::aRibBlurRestoreFrame; MObject shaveGlobals::aRibBlurShutterOpenOffset; MObject shaveGlobals::aRibBlurShutterCloseOffset; MObject shaveGlobals::aRibBlurTimeBasis; MObject shaveGlobals::aRibCompress; MObject shaveGlobals::aRibKeepRibFiles; MObject shaveGlobals::aRibLibOverride; MObject shaveGlobals::aRibNormals; MObject shaveGlobals::aRibOpacities; MObject shaveGlobals::aRibPrimitiveType; MObject shaveGlobals::aRibRootPositions; MObject shaveGlobals::aRibRootTipColors; MObject shaveGlobals::aRibStuff; MObject shaveGlobals::aRibTimeUnits; MObject shaveGlobals::aRibUVs; MObject shaveGlobals::aRibUVSet; MObject shaveGlobals::aRibWCoords; MObject shaveGlobals::aRibVertexColors; MObject shaveGlobals::aRibVoxelEnable; MObject shaveGlobals::aRibVoxelResolution; MObject shaveGlobals::aRibVoxelFullPaths; MObject shaveGlobals::displayDoFallbackAttr; MObject shaveGlobals::displayFallbackRatioAttr; MObject shaveGlobals::displayHairRatioAttr; MObject shaveGlobals::displayHiarDoXparency; // // Semi-Deprecated Attributes // MObject shaveGlobals::aUseGeomForShadows; bool shaveUseGeomShadowsGlob; MObject shaveGlobals::aShadowHairRatio; // // Deprecated Attributes // MObject shaveGlobals::aActiveShaveNode; MObject shaveGlobals::aCurrentShaveNode; MObject shaveGlobals::aDisplayDensity; MObject shaveGlobals::aDisplayHairDoSsao; MObject shaveGlobals::aFastBrush; MObject shaveGlobals::aGenerateHairGeometry; MObject shaveGlobals::aInstanceRenderMode; MObject shaveGlobals::aMREnableIrradiance; MObject shaveGlobals::aMRIrradiance; MObject shaveGlobals::aMROcclusionCollection; MObject shaveGlobals::aMRSafeMode; MObject shaveGlobals::aMRSatelliteSupport; MObject shaveGlobals::aMRUseRenderGlobalsCallbacks; MObject shaveGlobals::aPrmanCurvesSupported; MObject shaveGlobals::aRibBlurUseMayaDefaults; MObject shaveGlobals::aRibUseRenderGlobalsCallbacks; MObject shaveGlobals::aShadowAntiAlias; MObject shaveGlobals::aShadowQuality; MObject shaveGlobals::aShaveLightList; MObject shaveGlobals::aShavePrmanMode; MObject shaveGlobals::aShaveShadowFuzz; MObject shaveGlobals::aShaveShadowRes; MObject shaveGlobals::aShaveShadowSamples; MObject shaveGlobals::aTileCount; MObject shaveGlobals::aTrigger; MObject shaveGlobals::aUseDeepShadows; MObject shaveGlobals::aVrayDraFile; // Global Vars For Attr Values // // We're slowly deprecating these in favour of passing values using // shaveGlobals::Globals structs, so don't add any new ones here. bool doHairShadowsGlob; bool doShaveComp2dGlob; bool doShaveCompsGlob; bool enableInstanceGeometryGlob; float gravityGlob; int glisntGlob; MString hairFileNameGlob; bool keepHairRenderFilesGlob; bool liveModeGlob; bool liveModeRecord; bool liveModePlayback; float displayRatioGlob; float fallbackRatioGlob; bool displayGuidesGlob = false; float guideThickGlob; bool doFallbackGlob = true; //bool hideHairGlob = false; float displaySegmentLimitGlob; bool doHairXparencyGlob; int maxThreadsGlob = 0; bool nativeIlluminationGlob; shaveConstant::RenderMode normalRenderModeGlob; short renderQualityGlob; MString shaveSceneObjectsGlob; float shaveShadowDensityGlob; float shaveShadowHairRatioGlob; bool shaveShadowMatteGlob; MString tmpDirGlob; bool threadPerProcessorGlob = true; bool useAllLightsGlob; bool useDRAGlob = true; bool visibleInReflectionsGlob; int voxelResolutionGlob; MCallbackId idleEventId; bool shadowRender; float motionBlurSamplesGlob; shaveGlobals::shaveGlobals() : mHideHair(false) , mNodeVersion(0) , mNormalRenderMode(shaveConstant::kBufferRender) {} /* * Create all of the attributes of our shaveGlobals Dependency Node. */ MStatus shaveGlobals::initialize() { MStatus st; MFnEnumAttribute eAttr; MFnMessageAttribute mAttr; MFnNumericAttribute nAttr; MFnTypedAttribute tAttr; MFnUnitAttribute unitAttr; aInfo1 = nAttr.create("in1", "i1", MFnNumericData::kShort, 0); nAttr.setStorable(true); nAttr.setHidden(true); addAttribute(aInfo1); aInfo2 = nAttr.create("in2", "i2", MFnNumericData::kShort, 0); nAttr.setStorable(true); nAttr.setHidden(true); addAttribute(aInfo2); aNormalRenderMode = eAttr.create( "renderMode", "rndm", shaveConstant::kBufferRender ); eAttr.addField( shaveRender::getRenderModeName(shaveConstant::kBufferRender), shaveConstant::kBufferRender ); eAttr.addField( shaveRender::getRenderModeName(shaveConstant::kGeometryRender), shaveConstant::kGeometryRender ); eAttr.addField( shaveRender::getRenderModeName(shaveConstant::kNoRender), shaveConstant::kNoRender ); eAttr.setInternal(true); eAttr.setStorable(true); addAttribute(aNormalRenderMode); aEnableInstanceGeometry = nAttr.create("enableInstanceGeometry", "eig", MFnNumericData::kBoolean, true); addAttribute(aEnableInstanceGeometry); aLiveMode = nAttr.create ("liveMode", "slive", MFnNumericData::kBoolean, false); nAttr.setHidden(true); nAttr.setStorable(false); addAttribute (aLiveMode); aLiveModeRecord = nAttr.create ("liveModeRec", "rec", MFnNumericData::kBoolean, false); nAttr.setHidden(true); nAttr.setStorable(false); addAttribute (aLiveModeRecord); aLiveModePlayback = nAttr.create ("liveModePlay", "pla", MFnNumericData::kBoolean, false); nAttr.setHidden(true); nAttr.setStorable(false); addAttribute (aLiveModePlayback); aNativeIllumination = nAttr.create ("nativeIllumination", "nil", MFnNumericData::kBoolean, false); nAttr.setStorable(true); addAttribute (aNativeIllumination); aDoCompositing = nAttr.create ("doCompositing", "dsc", MFnNumericData::kBoolean, true); addAttribute (aDoCompositing); aComposite2d = nAttr.create ("composite2d", "c2d", MFnNumericData::kBoolean, true); addAttribute (aComposite2d); aDoHairShadows = nAttr.create ("doHairShadows", "dhs", MFnNumericData::kBoolean, true); addAttribute (aDoHairShadows); aUseAllLights = nAttr.create ("useAllLights", "ual", MFnNumericData::kBoolean, true); addAttribute(aUseAllLights); aShadowMatte = nAttr.create ("shadowMatte", "sm", MFnNumericData::kBoolean, false); addAttribute (aShadowMatte); aShadowMatteIncludeBackfacing = nAttr.create( "shadowMatteIncludeBackfacing", "smbf", MFnNumericData::kBoolean, true, &st ); MChkErr(st, "cannot create 'shadowMatteIncludeBackfacing' attribute."); st = addAttribute(aShadowMatteIncludeBackfacing); MChkErr(st, "cannot add 'shadowMatteIncludeBackfacing' attribute."); aKeepHairRenderFiles = nAttr.create ("keepHairPassPics", "khrf", MFnNumericData::kBoolean, false); addAttribute (aKeepHairRenderFiles); aRenderQuality = eAttr.create ("renderQuality", "rq", 1); eAttr.addField("Draft",0); eAttr.addField("Low",1); eAttr.addField("Medium", 2); eAttr.addField("High",3); eAttr.addField("Duuuude...",4); eAttr.setStorable(true); addAttribute (aRenderQuality); aHairFilename = tAttr.create("hairFilenamePrefix", "hfn", MFnData::kString, &st); addAttribute (aHairFilename); // // 'tmpDir' holds the user-defined path to the directory where the // scene's stat (dynamics) files will be stored. The unfortunate name // of the attribute is the result of history: originally it was viewed // as being a place to store temporary files, but the stat files are // less temporary than others. // // 'tmpDir' can hold either an absolute path, or a relative path which // is interpreted relative to the current project directory. // aStatFileDir = tAttr.create("tmpDir", "tpd", MFnData::kString, &st); tAttr.setStorable(true); addAttribute (aStatFileDir); aHairOcclusionObjects = tAttr.create( "hairOcclusionObjects", "sso", MFnData::kString, &st ); addAttribute (aHairOcclusionObjects); aShadowDensity = nAttr.create("shadowDensity", "sd", MFnNumericData::kFloat, 1.); nAttr.setMin(0.0); nAttr.setMax(1.0); addAttribute (aShadowDensity); aGravity = nAttr.create ("gravity", "grav", MFnNumericData::kFloat, 1.0); nAttr.setStorable(true); nAttr.setSoftMin(-2); nAttr.setSoftMax(2); addAttribute (aGravity); aGlInst = nAttr.create ("glInstances", "gli", MFnNumericData::kBoolean, /*0*/ 1); nAttr.setStorable(true); addAttribute (aGlInst); aNodeVersion = nAttr.create("nodeVersion", "nv", MFnNumericData::kLong); nAttr.setStorable(true); nAttr.setHidden(true); nAttr.setInternal(true); nAttr.setDefault(0); addAttribute(aNodeVersion); aUseDRA = nAttr.create( "useDRA", "dra", MFnNumericData::kBoolean, true ); #if !DRA_OPTIONAL nAttr.setInternal(true); #endif nAttr.setStorable(true); addAttribute(aUseDRA); aVoxelResolution = eAttr.create ("voxelResolution", "vxrs", 9); eAttr.addField("1x1x1",1); eAttr.addField("2x2x2",2); eAttr.addField("3x3x3",3); eAttr.addField("5x5x5",5); eAttr.addField("9x9x9",9); eAttr.addField("15x15x15",15); eAttr.addField("20x20x20",20); eAttr.addField("25x25x25",25); eAttr.setStorable(true); addAttribute(aVoxelResolution); aVisibleInReflections = nAttr.create( "visibleInReflections", "vrfl", MFnNumericData::kBoolean, false ); nAttr.setStorable(true); addAttribute(aVisibleInReflections); aHideHair = nAttr.create("hideHair", "hh", MFnNumericData::kBoolean, false); nAttr.setInternal(true); nAttr.setStorable(true); st = addAttribute(aHideHair); MChkErr(st, "Cannot add 'hideHair' attribute."); aMaxThreads = nAttr.create( "maxThreads", "mth", MFnNumericData::kLong, 0, &st ); MChkErr(st, "Cannot create 'maxThreads' attribute."); nAttr.setStorable(true); nAttr.setHidden(true); nAttr.setInternal(true); nAttr.setDefault(0); nAttr.setMin(0); nAttr.setMax(20); st = addAttribute(aMaxThreads); MChkErr(st, "Cannot add 'maxThreads' attribute."); aThreadPerProcessor = nAttr.create( "threadPerProcessor", "tpp", MFnNumericData::kBoolean, 0.0, &st ); MChkErr(st, "Cannot create 'threadPerProcessor' attribute."); nAttr.setInternal(true); nAttr.setDefault(true); st = addAttribute(aThreadPerProcessor); MChkErr(st, "Cannot add 'threadPerProcessor' attribute."); aVerbose = nAttr.create("verbose", "verb", MFnNumericData::kBoolean, true); nAttr.setStorable(true); st = addAttribute(aVerbose); MChkErr(st, "Cannot add 'verbose' attribute."); aVoxelScaling = nAttr.create( "voxelScaling", "vs", MFnNumericData::kFloat, 1.1, &st ); MChkErr(st, "Cannot create 'voxelScaling' attribute."); nAttr.setMin(0.1); nAttr.setSoftMax(2.0); st = addAttribute(aVoxelScaling); MChkErr(st, "Cannot add 'voxelScaling' attribute."); // Maya doesn't supply an MPlug method for reading the value of // a kAddr plug. So we use this attribute to allow us to read it // through an MDataHandle. See shaveUtil::getAddrPlugValue() aAddress = nAttr.createAddr("address", "addr", NULL, &st); MChkErr(st, "Cannot create 'address' attribute."); nAttr.setHidden(true); st = addAttribute(aAddress); MChkErr(st, "Cannot add 'address' attribute."); aTileMemoryLimit = nAttr.create( "tileMemoryLimit", "tml", MFnNumericData::kInt, /*90.0*/ 180.0, &st ); MChkErr(st, "Cannot create 'tileMemoryLimit' attribute."); nAttr.setStorable(true); nAttr.setMin(1); nAttr.setSoftMax(1000); st = addAttribute(aTileMemoryLimit); MChkErr(st, "Cannot add 'tileMemoryLimit' attribute."); aTransparencyDepth = nAttr.create( "transparencyDepth", "td", MFnNumericData::kInt, 30.0, &st ); MChkErr(st, "Cannot create 'transparencyDepth' attribute."); nAttr.setStorable(true); nAttr.setMin(0); nAttr.setSoftMax(100); st = addAttribute(aTransparencyDepth); MChkErr(st, "Cannot add 'transparencyDepth' attribute."); // RIB-Related Attributes aRibBinary = nAttr.create( "ribBinary", "rbin", MFnNumericData::kBoolean, 0.0, &st ); MChkErr(st, "Cannot create 'ribBinary' attribute."); nAttr.setDefault(false); st = addAttribute(aRibBinary); MChkErr(st, "Cannot add 'ribBinary' attribute."); aRibBlurTimeBasis = eAttr.create( "ribBlurTimeBasis", "rbtb", shaveConstant::kTimeRelative, &st ); MChkErr(st, "Cannot create 'ribBlurTimeBasis' attribute."); eAttr.addField("Absolute", shaveConstant::kTimeAbsolute); eAttr.addField("Relative", shaveConstant::kTimeRelative); st = addAttribute(aRibBlurTimeBasis); MChkErr(st, "Cannot add 'ribBlurTimeBasis' attribute."); aRibBlurEnable = nAttr.create( "ribBlurEnable", "rben", MFnNumericData::kBoolean, 0.0, &st ); MChkErr(st, "Cannot create 'ribBlurEnable' attribute."); nAttr.setDefault(false); st = addAttribute(aRibBlurEnable); MChkErr(st, "Cannot add 'ribBlurEnable' attribute."); aRibBlurInheritSettings = eAttr.create( "ribBlurInheritSettings", "rbis", shaveConstant::kRibBlurInheritMaya, &st ); MChkErr(st, "Cannot create 'ribBlurInheritSettings' attribute."); eAttr.addField("Off", shaveConstant::kRibBlurInheritOff); eAttr.addField("Maya Globals", shaveConstant::kRibBlurInheritMaya); eAttr.addField("RfM Studio", shaveConstant::kRibBlurInheritRenderman); eAttr.setStorable(true); st = addAttribute(aRibBlurInheritSettings); MChkErr(st, "Cannot add 'ribBlurInheritSettings' attribute."); aRibBlurRestoreFrame = nAttr.create( "ribBlurRestoreFrame", "rbrf", MFnNumericData::kBoolean, 0.0, &st ); MChkErr(st, "Cannot create 'ribBlurRestoreFrame' attribute."); nAttr.setDefault(true); st = addAttribute(aRibBlurRestoreFrame); MChkErr(st, "Cannot add 'ribBlurRestoreFrame' attribute."); aRibBlurShutterCloseOffset = nAttr.create( "ribBlurShutterCloseOffset", "rbsc", MFnNumericData::kFloat, 0.3, &st ); MChkErr(st, "Cannot create 'ribBlurShutterCloseOffset' attribute."); nAttr.setSoftMin(0.0); nAttr.setSoftMax(1.0); st = addAttribute(aRibBlurShutterCloseOffset); MChkErr(st, "Cannot add 'ribBlurShutterCloseOffset' attribute."); aRibBlurShutterOpenOffset = nAttr.create( "ribBlurShutterOpenOffset", "rbso", MFnNumericData::kFloat, -0.3, &st ); MChkErr(st, "Cannot create 'ribBlurShutterOpenOffset' attribute."); nAttr.setSoftMin(-1.0); nAttr.setSoftMax(0.0); st = addAttribute(aRibBlurShutterOpenOffset); MChkErr(st, "Cannot add 'ribBlurShutterOpenOffset' attribute."); aRibCompress = nAttr.create( "ribCompress", "rcmp", MFnNumericData::kBoolean, 0.0, &st ); MChkErr(st, "Cannot create 'ribCompress' attribute."); nAttr.setDefault(false); st = addAttribute(aRibCompress); MChkErr(st, "Cannot add 'ribCompress' attribute."); aRibKeepRibFiles = nAttr.create( "ribKeepRibFiles", "rkrf", MFnNumericData::kBoolean, 0.0, &st ); MChkErr(st, "Cannot create 'ribKeepRibFiles' attribute."); nAttr.setDefault(false); st = addAttribute(aRibKeepRibFiles); MChkErr(st, "Cannot add 'ribKeepRibFiles' attribute."); aRibLibOverride = tAttr.create( "ribLibOverride", "rlo", MFnData::kString, MObject::kNullObj, &st ); MChkErr(st, "Cannot create 'ribLibOverride' attribute."); tAttr.setUsedAsFilename(true); st = addAttribute(aRibLibOverride); MChkErr(st, "Cannot add 'ribLibOverride' attribute."); aRibNormals = nAttr.create( "ribNormals", "rnrm", MFnNumericData::kBoolean, 0.0, &st ); MChkErr(st, "Cannot create 'ribNormals' attribute."); nAttr.setDefault(false); st = addAttribute(aRibNormals); MChkErr(st, "Cannot add 'ribNormals' attribute."); aRibOpacities = nAttr.create( "ribOpacities", "ropa", MFnNumericData::kBoolean, 0.0, &st ); MChkErr(st, "Cannot create 'ribOpacities' attribute."); nAttr.setDefault(true); st = addAttribute(aRibOpacities); MChkErr(st, "Cannot add 'ribOpacities' attribute."); aRibPrimitiveType = eAttr.create("hairPrimitiveType", "prhpt", 1, &st); MChkErr(st, "Cannot create 'hairPrimitiveType' attribute."); eAttr.addField("Linear Curve", 0); eAttr.addField("Cubic Curve", 1); st = addAttribute(aRibPrimitiveType); MChkErr(st, "Cannot add 'hairPrimitiveType' attribute."); aRibRootPositions = nAttr.create( "ribRootPositions", "rrp", MFnNumericData::kBoolean, 0.0, &st ); MChkErr(st, "Cannot create 'ribRootPositions' attribute."); nAttr.setDefault(false); st = addAttribute(aRibRootPositions); MChkErr(st, "Cannot add 'ribRootPositions' attribute."); aRibRootTipColors = nAttr.create( "ribRootTipColors", "rrtc", MFnNumericData::kBoolean, 0.0, &st ); MChkErr(st, "Cannot create 'ribRootTipColors' attribute."); nAttr.setDefault(true); st = addAttribute(aRibRootTipColors); MChkErr(st, "Cannot add 'ribRootTipColors' attribute."); // See the createShaveGlobals() proc in shaveUI.mel for the setting of // this attribute's default value. aRibStuff = tAttr.create( "ribStuff", "rst", MFnData::kString, MObject::kNullObj, &st ); MChkErr(st, "Cannot create 'ribStuff' attribute."); st = addAttribute(aRibStuff); MChkErr(st, "Cannot add 'ribStuff' attribute."); aRibVertexColors = nAttr.create( "ribVertexColors", "rvc", MFnNumericData::kBoolean, 0.0, &st ); MChkErr(st, "Cannot create 'ribVertexColors' attribute."); nAttr.setDefault(false); st = addAttribute(aRibVertexColors); MChkErr(st, "Cannot add 'ribVertexColors' attribute."); aRibTimeUnits = eAttr.create("ribTimeUnits", "rtu", kFrames, &st); MChkErr(st, "Cannot create 'ribTimeUnits' attribute."); eAttr.addField("frames", kFrames); eAttr.addField("seconds", kSeconds); st = addAttribute(aRibTimeUnits); MChkErr(st, "Cannot add 'ribTimeUnits' attribute."); aRibUVs= nAttr.create("ribUVs", "ruv", MFnNumericData::kBoolean, 0.0, &st); MChkErr(st, "Cannot create 'ribUVs' attribute."); nAttr.setDefault(false); st = addAttribute(aRibUVs); MChkErr(st, "Cannot add 'ribUVs' attribute."); aRibUVSet= tAttr.create( "ribUVSet", "ruvs", MFnData::kString, MObject::kNullObj, &st ); MChkErr(st, "Cannot create 'ribUVSet' attribute."); st = addAttribute(aRibUVSet); MChkErr(st, "Cannot add 'ribUVSet' attribute."); aRibWCoords = nAttr.create( "ribWCoords", "rwc", MFnNumericData::kBoolean, 0.0, &st ); MChkErr(st, "Cannot create 'ribWCoords' attribute."); nAttr.setDefault(false); st = addAttribute(aRibWCoords); MChkErr(st, "Cannot add 'ribWCoords' attribute."); aRibVoxelEnable= nAttr.create( "ribVoxelEnable", "rvxe", MFnNumericData::kBoolean, 0.0, &st ); MChkErr(st, "Cannot create 'ribVoxelEnable' attribute."); nAttr.setDefault(false); st = addAttribute(aRibVoxelEnable); MChkErr(st, "Cannot add 'ribVoxelEnable' attribute."); aRibVoxelFullPaths= nAttr.create( "ribVoxelFullPaths", "rvxp", MFnNumericData::kBoolean, 0.0, &st ); MChkErr(st, "Cannot create 'ribVoxelFullPaths' attribute."); nAttr.setDefault(false); st = addAttribute(aRibVoxelFullPaths); MChkErr(st, "Cannot add 'ribVoxelFullPaths' attribute."); aRibVoxelResolution= eAttr.create("ribVoxelResolution", "rvxr", 20, &st); MChkErr(st, "Cannot create 'ribVoxelResolution' attribute."); eAttr.addField("1x1x1",1); eAttr.addField("2x2x2",2); eAttr.addField("3x3x3",3); eAttr.addField("5x5x5",5); eAttr.addField("9x9x9",9); eAttr.addField("15x15x15",15); eAttr.addField("20x20x20",20); eAttr.addField("40x40x40",40); eAttr.setStorable(true); st = addAttribute(aRibVoxelResolution); MChkErr(st, "Cannot add 'ribVoxelResolution' attribute."); displayHairRatioAttr = nAttr.create( "displayHairRatio", "dhr", MFnNumericData::kFloat, 50.0f ); nAttr.setMin(0.0f); nAttr.setMax(100.0f); st = addAttribute(displayHairRatioAttr); MChkErr(st, "can't add 'displayHairRatio' attribute."); displayFallbackRatioAttr = nAttr.create( "displayFallbackRatio", "dfr", MFnNumericData::kFloat, 10.0f ); nAttr.setMin(0.0f); nAttr.setMax(100.0f); st = addAttribute(displayFallbackRatioAttr); MChkErr(st, "can't add 'displayRatio' attribute."); displayDoFallbackAttr = nAttr.create( "doFallback", "dof", MFnNumericData::kBoolean, 1 ); nAttr.setStorable(false); st = addAttribute(displayDoFallbackAttr); MChkErr(st, "can't add 'doFallback' attribute."); aDisplayGuides = nAttr.create( "displayGuides", "dg", MFnNumericData::kBoolean, 0, &st ); MChkErr(st, "can't create 'displayGuides' attribute."); nAttr.setDefault(false); st = addAttribute(aDisplayGuides); MChkErr(st, "can't add 'displayGuides' attribute."); aDisplaySegmentLimit = nAttr.create( "displaySegmentLimit", "dsl", MFnNumericData::kFloat, 50.0f, &st ); MChkErr(st, "can't create 'displaySegmentLimit' attribute."); nAttr.setHidden(true); // So it doesn't get saved as a preset. nAttr.setMin(1.0f); nAttr.setSoftMax(100.0f); st = addAttribute(aDisplaySegmentLimit); MChkErr(st, "can't add 'displaySegmentLimit' attribute."); aDisplayGuideThick = nAttr.create( "displayGuideThick", "dgt", MFnNumericData::kFloat, 0.2, &st ); MChkErr(st, "can't create 'displayGuideThick' attribute."); nAttr.setHidden(true); // So it doesn't get saved as a preset. nAttr.setMin(0.001f); nAttr.setSoftMax(1.0f); nAttr.setDefault(/*0.7f*/ 0.2f); st = addAttribute(aDisplayGuideThick); MChkErr(st, "can't add 'displayGuideThick' attribute."); displayHiarDoXparency = nAttr.create( "displayHairTransprency", "dht", MFnNumericData::kBoolean, true ); st = addAttribute(displayHiarDoXparency); //******************************************************* // // Semi-Deprecated Attributes // // (Functionality hidden but still present.) // //******************************************************* aUseGeomForShadows = nAttr.create( "useGeomForShadows", "ugs", MFnNumericData::kBoolean, false ); nAttr.setHidden(true); nAttr.setStorable(false); addAttribute(aUseGeomForShadows); aShadowHairRatio = nAttr.create( "shadowHairRatio", "shr", MFnNumericData::kFloat, 0.15 ); nAttr.setStorable(true); nAttr.setMin(0.0); nAttr.setMax(1.0); nAttr.setHidden(true); addAttribute(aShadowHairRatio); //******************************************************* // // Deprecated Attributes // //******************************************************* aActiveShaveNode = mAttr.create("activeShaveNode", "asn"); mAttr.setArray(true); mAttr.setHidden(true); mAttr.setWritable(true); mAttr.setReadable(false); // Don't allow outgoing connections. mAttr.setStorable(false); mAttr.setIndexMatters(false); addAttribute(aActiveShaveNode); aCurrentShaveNode = mAttr.create("currentShaveNode", "csn"); mAttr.setHidden(true); mAttr.setStorable(false); addAttribute(aCurrentShaveNode); aDisplayHairDoSsao = nAttr.create( "displayHairSsao", "dho", MFnNumericData::kBoolean, false ); nAttr.setHidden(true); nAttr.setStorable(false); st = addAttribute(aDisplayHairDoSsao); aDisplayDensity = eAttr.create("displayLod", "dns", 1); eAttr.addField("Off", -1); eAttr.addField("Low", 0); eAttr.addField("Medium", 1); eAttr.addField("High", 2); eAttr.setHidden(true); eAttr.setStorable(false); addAttribute(aDisplayDensity); aGenerateHairGeometry = nAttr.create( "doHairGeometry", "mhg", MFnNumericData::kBoolean, false ); nAttr.setHidden(true); nAttr.setStorable(false); addAttribute(aGenerateHairGeometry); aFastBrush = nAttr.create( "fastBrush", "fb", MFnNumericData::kBoolean, 0.0, &st ); nAttr.setDefault(false); nAttr.setHidden(true); nAttr.setStorable(false); st = addAttribute(aFastBrush); aInstanceRenderMode = eAttr.create( "instanceRenderMode", "irnm", shaveConstant::kGeometryRender ); eAttr.addField( shaveRender::getRenderModeName(shaveConstant::kBufferRender), shaveConstant::kBufferRender ); eAttr.addField( shaveRender::getRenderModeName(shaveConstant::kGeometryRender), shaveConstant::kGeometryRender ); eAttr.addField( shaveRender::getRenderModeName(shaveConstant::kNoRender), shaveConstant::kNoRender ); eAttr.setHidden(true); eAttr.setStorable(false); addAttribute(aInstanceRenderMode); aMREnableIrradiance = nAttr.create( "mrEnableIrradiance", "mrei", MFnNumericData::kBoolean, false, &st ); nAttr.setHidden(true); nAttr.setStorable(false); nAttr.setDefault(false); addAttribute(aMREnableIrradiance); aMRIrradiance = nAttr.create( "mrIrradiance", "mrir", MFnNumericData::kFloat, 1.0, &st ); nAttr.setHidden(true); nAttr.setStorable(false); addAttribute(aMRIrradiance); aMROcclusionCollection = nAttr.create( "mrOcclusionCollection", "mroc", MFnNumericData::kBoolean, false ); nAttr.setHidden(true); nAttr.setStorable(false); addAttribute(aMROcclusionCollection); aMRSafeMode = nAttr.create( "mrSafeMode", "mrsm", MFnNumericData::kBoolean, false ); nAttr.setHidden(true); nAttr.setStorable(false); addAttribute(aMRSafeMode); aMRSatelliteSupport = nAttr.create( "mrSatelliteSupport", "mss", MFnNumericData::kBoolean, false ); nAttr.setHidden(true); nAttr.setStorable(false); addAttribute(aMRSatelliteSupport); aMRUseRenderGlobalsCallbacks = nAttr.create( "mrUseRenderGlobalsCallbacks", "rgcb", MFnNumericData::kBoolean, true ); nAttr.setHidden(true); nAttr.setStorable(false); addAttribute(aMRUseRenderGlobalsCallbacks); aPrmanCurvesSupported = nAttr.create( "prmanCurvesSupported", "pmcs", MFnNumericData::kBoolean, true ); nAttr.setHidden(true); nAttr.setStorable(false); addAttribute(aPrmanCurvesSupported); aRibBlurUseMayaDefaults = nAttr.create( "ribBlurUseMayaDefaults", "rbum", MFnNumericData::kBoolean, 0.0, &st ); nAttr.setHidden(true); nAttr.setStorable(false); st = addAttribute(aRibBlurUseMayaDefaults); aRibUseRenderGlobalsCallbacks = nAttr.create( "ribUseRenderGlobalsCallbacks", "rbrg", MFnNumericData::kBoolean, true ); nAttr.setHidden(true); nAttr.setStorable(false); addAttribute(aRibUseRenderGlobalsCallbacks); aShadowAntiAlias = eAttr.create ("shadowAntialiasing", "shadaa", 1); eAttr.addField("Draft", 1); eAttr.addField("Low",3); eAttr.addField("Medium",5); eAttr.addField("High", 10); eAttr.setHidden(true); eAttr.setStorable(false); addAttribute(aShadowAntiAlias); aShadowQuality = eAttr.create("shadowQuality", "sq", kHighShadowQuality); eAttr.addField("Low", kLowShadowQuality); eAttr.addField("Medium", kMediumShadowQuality); eAttr.addField("High", kHighShadowQuality); eAttr.setHidden(true); eAttr.setStorable(false); addAttribute(aShadowQuality); aShaveLightList = tAttr.create("shaveLightList", "sll", MFnData::kString); tAttr.setHidden(true); tAttr.setStorable(false); addAttribute(aShaveLightList); aShavePrmanMode = nAttr.create( "prmanMode", "sprmm", MFnNumericData::kBoolean, false ); nAttr.setHidden(true); nAttr.setStorable(false); addAttribute(aShavePrmanMode); aShaveShadowFuzz = nAttr.create("shaveShadFuzz", "ssfuzz", MFnNumericData::kFloat, 8.0); nAttr.setHidden(true); nAttr.setStorable(false); addAttribute(aShaveShadowFuzz); aShaveShadowRes = nAttr.create("shadowResolution", "ssr", MFnNumericData::kShort, 1400); nAttr.setHidden(true); nAttr.setStorable(false); addAttribute(aShaveShadowRes); aShaveShadowSamples = nAttr.create( "shaveShadSamp", "sssamp", MFnNumericData::kShort, 0 ); nAttr.setHidden(true); nAttr.setStorable(false); addAttribute(aShaveShadowSamples); aTrigger = tAttr.create("trigger", "trg", MFnData::kMesh); tAttr.setHidden(true); tAttr.setStorable(false); addAttribute(aTrigger); aTileCount = eAttr.create("tileCount", "srtc", 3); eAttr.addField("1x1",1); eAttr.addField("2x2", 2); eAttr.addField("3x3",3); eAttr.addField("5x5", 5); eAttr.addField("9x9", 9); eAttr.addField("15x15", 15); eAttr.addField("25x25", 25); eAttr.addField("40x40", 40); eAttr.setHidden(true); eAttr.setStorable(false); addAttribute(aTileCount); aUseDeepShadows = nAttr.create( "useDeepShadows", "uds", MFnNumericData::kBoolean ); nAttr.setHidden(true); tAttr.setStorable(false); addAttribute(aUseDeepShadows); //default dra file name, //artist can edit it to resolve confilt when rendering //multiple scenes on same machine -- dub|23-09-2010 MStatus stat; //char buf[200]; //time_t t; //time(&t); //srand((unsigned int)t); //int rsuf = rand(); //sprintf(buf,"vrayHair_%i.dra",rsuf); //MFnStringData strData; //strData.create(buf,&stat); MFnStringData strData; strData.create("",&stat); if(stat != MStatus::kSuccess) MGlobal::displayError("ShaveGlobals: can not create MFnStringData."); aVrayDraFile = tAttr.create( "vrayDraFile", "vrd", MFnData::kString,strData.object(), &stat); if(stat != MStatus::kSuccess) MGlobal::displayError("ShaveGlobals: can not create 'vrayDraFile' string attribute."); else { tAttr.setHidden ( false ); tAttr.setKeyable ( false ); tAttr.setStorable( true ); } addAttribute(aVrayDraFile); aPrimCameraVis = nAttr.create("primCameraVis", "pcv", MFnNumericData::kBoolean, true); nAttr.setStorable(true); st = addAttribute(aPrimCameraVis); MChkErr(st, "Cannot add 'primCameraVis' attribute."); aPrimLightVis = nAttr.create("primLightVis", "plv", MFnNumericData::kBoolean, true); nAttr.setStorable(true); st = addAttribute(aPrimLightVis); MChkErr(st, "Cannot add 'primGiVis' attribute."); aPrimGiVis = nAttr.create("primGiVis", "pgv", MFnNumericData::kBoolean, true); nAttr.setStorable(true); st = addAttribute(aPrimGiVis); MChkErr(st, "Cannot add 'primGiVis' attribute."); return MS::kSuccess; } MStatus shaveGlobals::shouldSave(const MPlug& plug, bool& saveIt) { // // If it's a dynamic attribute, or one of the standard MPxNode // attributes, then do the default handling. // MFnDependencyNode nodeFn(thisMObject()); MFnDependencyNode::MAttrClass attrClass; attrClass = nodeFn.attributeClass(plug.attribute()); if ((attrClass == MFnDependencyNode::kLocalDynamicAttr) || (plug == MPxNode::message) || (plug == MPxNode::isHistoricallyInteresting) || (plug == MPxNode::caching) || (plug == MPxNode::state)) { return MS::kInvalidParameter; } // // Everything else we will save all the time. That way if we decide to // change defaults at some later time, we won't screw up old scene // files. // saveIt = true; return MS::kSuccess; } void* shaveGlobals::creator() { return new shaveGlobals; } bool shaveGlobals::deleteMe(MDGModifier& dgMod) { MFnDependencyNode nodeFn(thisMObject()); // // We can't delete the node if it's from a referenced file. // if (nodeFn.isFromReferencedFile()) return false; if (nodeFn.isLocked()) nodeFn.setLocked(false); MStatus st = dgMod.deleteNode(thisMObject()); return st; } void* shaveGlobals::getAddress() { MDataBlock block = forceCache(); return block.inputValue(aAddress).asAddr(); } MObject shaveGlobals::getDefaultNode() { MObject node = getDefaultNodeInternal(); // // If no shaveGlobals node was found, try to create one. // if (node.isNull()) { MGlobal::executeCommand("shaveGlobals"); node = getDefaultNodeInternal(); } return node; } MObject shaveGlobals::getDefaultNodeInternal() { MSelectionList list; list.add(defaultNodeName); MObject node; list.getDependNode(0, node); return node; } MStatus shaveGlobals::getGlobals() { // // Get the shave globals node // MObject shaveGlobalsNode = getDefaultNode(); if (shaveGlobalsNode.isNull()) return MS::kFailure; // // This method gets called fairly often (e.g. 4 during render init & // cleanup, plus 4 per frame rendered) so let's make sure it's fast by // grabbing a datablock and getting the values from that. // MFnDependencyNode nodeFn(shaveGlobalsNode); shaveGlobals* nodePtr = (shaveGlobals*)nodeFn.userNode(); if (!nodePtr) return MS::kFailure; return nodePtr->getGlobalsInternal(); } // Deprecated // // This version is being phased out in favour of the one which copies its // values into a Globals struct. Do not add any new attrs here. MStatus shaveGlobals::getGlobalsInternal() { MDataBlock block = forceCache(); doHairShadowsGlob = block.inputValue(aDoHairShadows).asBool(); doShaveCompsGlob = block.inputValue(aDoCompositing).asBool(); doShaveComp2dGlob = block.inputValue(aComposite2d).asBool(); gravityGlob = block.inputValue(aGravity).asFloat(); glisntGlob = block.inputValue(aGlInst).asInt(); //if(gi != glisntGlob) //{ // glisntGlob = gi; //MFnDagNode nodeFn; //MDagPathArray paths; //shaveUtil::getShaveNodes(paths); //for (unsigned int i = 0; i < paths.length(); i++) //{ // nodeFn.setObject(paths[i].node()); // if (nodeFn.typeId() == shaveHairShape::id) // { // shaveHairShape* shape = (shaveHairShape*)nodeFn.userNode(); // shape->dirtyDisplay(); // float trigger; // MPlug triggerPlug = nodeFn.findPlug("trigger"); // triggerPlug.getValue(trigger); // triggerPlug.setValue(trigger+1.0f); // } //} //} hairFileNameGlob = block.inputValue(aHairFilename).asString(); keepHairRenderFilesGlob = block.inputValue(aKeepHairRenderFiles).asBool(); liveModeGlob = block.inputValue(aLiveMode).asBool(); displayRatioGlob = 0.01f*block.inputValue(displayHairRatioAttr).asFloat(); // doFallbackGlob = block.inputValue(displayDoFallbackAttr).asBool(); //just a trigger displayGuidesGlob = block.inputValue(aDisplayGuides).asBool(); fallbackRatioGlob = 0.01f*block.inputValue(displayFallbackRatioAttr).asFloat(); displaySegmentLimitGlob = block.inputValue(aDisplaySegmentLimit).asFloat(); guideThickGlob = block.inputValue(aDisplayGuideThick).asFloat(); doHairXparencyGlob = block.inputValue(displayHiarDoXparency).asBool(); nativeIlluminationGlob = block.inputValue(aNativeIllumination).asBool(); renderQualityGlob = block.inputValue(aRenderQuality).asShort(); shaveShadowMatteGlob = block.inputValue(aShadowMatte).asBool(); shaveSceneObjectsGlob = block.inputValue(aHairOcclusionObjects).asString(); shaveShadowDensityGlob = block.inputValue(aShadowDensity).asFloat(); shaveUseGeomShadowsGlob = block.inputValue(aUseGeomForShadows).asBool(); shaveShadowHairRatioGlob= block.inputValue(aShadowHairRatio).asFloat(); tmpDirGlob = block.inputValue(aStatFileDir).asString(); useAllLightsGlob = block.inputValue(aUseAllLights).asBool(); #if DRA_OPTIONAL useDRAGlob = block.inputValue(aUseDRA).asBool(); #endif visibleInReflectionsGlob= block.inputValue(aVisibleInReflections).asBool(); voxelResolutionGlob = (int)block.inputValue(aVoxelResolution).asShort(); enableInstanceGeometryGlob = block.inputValue(aEnableInstanceGeometry).asBool(); // // Internal Attributes // ------------------- // // Internal attributes need special handling. A value which was set // via 'setAttr' or an MPlug will not appear in the datablock, which // means that we need to get it from our internal storage. However, if // there is a connection to the attr and it is dirty, the new value // won't be in our internal storage yet, so we need to build its data // handle to force the update. // // Put it all together and it means that we must first build the // attribute's handle, to ensure that dirty connections are evaluated, // but then we must ignore the handle and retrieve the value from our // internal storage. // MDataHandle hdl = block.inputValue(aNormalRenderMode); normalRenderModeGlob = mNormalRenderMode; // // For the following internal attrs, the global var *is* our internal // storage, so there's no value to copy. // hdl = block.inputValue(aMaxThreads); hdl = block.inputValue(aThreadPerProcessor); #if !DRA_OPTIONAL hdl = block.inputValue(aUseDRA); #endif return MS::kSuccess; } MStatus shaveGlobals::getGlobals(shaveGlobals::Globals& g) { // // Get the shave globals node // MObject shaveGlobalsNode = getDefaultNode(); if (shaveGlobalsNode.isNull()) return MS::kFailure; // // This method gets called fairly often (e.g. 4 times during render // init & cleanup, plus 4 per frame rendered) so let's make sure it's // fast by grabbing a datablock and getting the values from that. // MFnDependencyNode nodeFn(shaveGlobalsNode); shaveGlobals* nodePtr = (shaveGlobals*)nodeFn.userNode(); if (!nodePtr) return MS::kFailure; return nodePtr->getGlobalsInternal(g); } MStatus shaveGlobals::getGlobalsInternal(shaveGlobals::Globals& g) { MDataBlock block = forceCache(); glisntGlob = block.inputValue(aGlInst).asInt(); //if(gi != glisntGlob) //{ // glisntGlob = gi; /* MFnDagNode nodeFn; MDagPathArray paths; shaveUtil::getShaveNodes(paths); for (unsigned int i = 0; i < paths.length(); i++) { nodeFn.setObject(paths[i].node()); if (nodeFn.typeId() == shaveHairShape::id) { shaveHairShape* shape = (shaveHairShape*)nodeFn.userNode(); shape->dirtyDisplay(); float trigger; MPlug triggerPlug = nodeFn.findPlug("trigger"); triggerPlug.getValue(trigger); triggerPlug.setValue(trigger+1.0f); } }*/ //} g.composite2d = block.inputValue(aComposite2d).asBool(); g.doCompositing = block.inputValue(aDoCompositing).asBool(); g.doHairShadows = block.inputValue(aDoHairShadows).asBool(); g.enableInstanceGeometry= block.inputValue(aEnableInstanceGeometry).asBool(); g.gravity = block.inputValue(aGravity).asFloat(); g.glinst = block.inputValue(aGlInst).asInt(); g.hairFileNamePrefix = block.inputValue(aHairFilename).asString(); g.keepHairRenderFiles = block.inputValue(aKeepHairRenderFiles).asBool(); g.liveMode = block.inputValue(aLiveMode).asBool(); g.occlusionObjects = block.inputValue(aHairOcclusionObjects).asString(); g.renderQuality = block.inputValue(aRenderQuality).asShort(); g.shadowDensity = block.inputValue(aShadowDensity).asFloat(); g.shadowMatte = block.inputValue(aShadowMatte).asBool(); g.shadowMatteIncludeBackfacing = block.inputValue(aShadowMatteIncludeBackfacing).asBool(); g.tileMemoryLimit = (unsigned int)block.inputValue(aTileMemoryLimit).asInt(); g.transparencyDepth = (unsigned int)block.inputValue(aTransparencyDepth).asInt(); g.useGeomShadows = block.inputValue(aUseGeomForShadows).asBool(); g.shadowHairRatio = block.inputValue(aShadowHairRatio).asFloat(); g.statFileDir = block.inputValue(aStatFileDir).asString(); g.useAllLights = block.inputValue(aUseAllLights).asBool(); #if DRA_OPTIONAL g.useDRA = block.inputValue(aUseDRA).asBool(); #endif g.useNativeIllumination = block.inputValue(aNativeIllumination).asBool(); g.verbose = block.inputValue(aVerbose).asBool(); g.visibleInReflections = block.inputValue(aVisibleInReflections).asBool(); g.voxelResolution = (int)block.inputValue(aVoxelResolution).asShort(); g.voxelScaling = block.inputValue(aVoxelScaling).asFloat(); g.cameraVis = block.inputValue(aPrimCameraVis).asBool(); g.lightVis = block.inputValue(aPrimLightVis).asBool(); g.giVis = block.inputValue(aPrimGiVis).asBool(); // RIB Attributes g.rib.binary = block.inputValue(aRibBinary).asBool(); g.rib.compress = block.inputValue(aRibCompress).asBool(); g.rib.filePreamble = block.inputValue(aRibStuff).asString(); g.rib.libOverride = block.inputValue(aRibLibOverride).asString(); g.rib.keepRibFiles = block.inputValue(aRibKeepRibFiles).asBool(); g.rib.normals = block.inputValue(aRibNormals).asBool(); g.rib.opacities = block.inputValue(aRibOpacities).asBool(); g.rib.primitiveType = block.inputValue(aRibPrimitiveType).asShort(); g.rib.rootPositions = block.inputValue(aRibRootPositions).asBool(); g.rib.rootTipColors = block.inputValue(aRibRootTipColors).asBool(); g.rib.timeUnits = (RibTimeUnits)block.inputValue(aRibTimeUnits).asShort(); g.rib.uvCoords = block.inputValue(aRibUVs).asBool(); g.rib.uvSet = block.inputValue(aRibUVSet).asString(); g.rib.vertexColors = block.inputValue(aRibVertexColors).asBool(); g.rib.wCoords = block.inputValue(aRibWCoords).asBool(); g.rib.blur.enable = block.inputValue(aRibBlurEnable).asBool(); g.rib.blur.inheritSettings = block.inputValue(aRibBlurInheritSettings).asShort(); g.rib.blur.restoreFrame = block.inputValue(aRibBlurRestoreFrame).asBool(); g.rib.blur.shutterCloseOffset = block.inputValue(aRibBlurShutterCloseOffset).asFloat(); g.rib.blur.shutterOpenOffset = block.inputValue(aRibBlurShutterOpenOffset).asFloat(); g.rib.blur.timeBasis = block.inputValue(aRibBlurTimeBasis).asShort(); g.rib.voxels.enable = block.inputValue(aRibVoxelEnable).asBool(); g.rib.voxels.fullPaths = block.inputValue(aRibVoxelFullPaths).asBool(); g.rib.voxels.resolution = block.inputValue(aRibVoxelResolution).asShort(); // Preferences Stored In optionVars bool exists = false; int iValue; iValue = MGlobal::optionVarIntValue("shave_fastBrush", &exists); if (!exists) iValue = 0; g.fastBrush = (iValue != 0); // // Internal Attributes // ------------------- // // Internal attributes need special handling. A value which was set // via 'setAttr' or an MPlug will not appear in datablock, which means // that we need to get it from our internal storage. However, if there // is a connection to the attr and it is dirty, the new value won't be // in our internal storage yet, so we need to build its data handle to // force the update. // // Put it all together and it means that we must first build the // attribute's handle, to ensure that dirty connections are evaluated, // but then we must ignore the handle and retrieve the value from our // internal storage. // MDataHandle hdl = block.inputValue(aNormalRenderMode); g.normalRenderMode = mNormalRenderMode; hdl = block.inputValue(aMaxThreads); g.maxThreads = maxThreadsGlob; hdl = block.inputValue(aThreadPerProcessor); g.threadPerProcessor = threadPerProcessorGlob; #if !DRA_OPTIONAL hdl = block.inputValue(aUseDRA); g.useDRA = true; #endif return MS::kSuccess; } MString getSceneName() { MString sceneName; MStringArray splitPath; MGlobal::executeCommand ("file -q -sn", sceneName); if(sceneName.length() != 0) { splitPath.clear(); sceneName.split('/',splitPath); sceneName = splitPath[splitPath.length()-1]; splitPath.clear(); sceneName.split('.',splitPath); sceneName = splitPath[0]; } else sceneName = "untitled"; return sceneName; } short buildh(char* id) { short h = 1; short i; for(i = 0; i < (short)(strlen(id)); i++) { h = h + (short)id[i]; } return h; } short buildk(short val) { short h; h = (short)(2.5*val)-(short)(4.5*val); return h; } #if MAYA_API_VERSION >= 20180000 bool shaveGlobals::getInternalValue(const MPlug &plug, MDataHandle &hdl) #else bool shaveGlobals::getInternalValueInContext( const MPlug& plug, MDataHandle& hdl, MDGContext& ) #endif { if (plug == aNormalRenderMode) hdl.set((short)mNormalRenderMode); else if (plug == aNodeVersion) { // // If the version is zero then it has not yet been explicitly set, // so we must determine an appropriate value. // if (mNodeVersion == 0) { // // If we're in the middle of file loading, we might still be // awaiting the set command so we should continue to return 0. // Otherwise we assume that this is a newly-created node and // return the latest version. // // I used to do this in the postConstructor() but that was // causing random crashes within Maya, so we do it here now, // instead. // if (!shaveUtil::isLoadingFile()) mNodeVersion = kNodeVersion; } hdl.set(mNodeVersion); } else if (plug == aHideHair) hdl.set(mHideHair); else if (plug == aMaxThreads) hdl.set(maxThreadsGlob); else if (plug == aThreadPerProcessor) hdl.set(threadPerProcessorGlob); #if !DRA_OPTIONAL else if (plug == aUseDRA) hdl.set(true); #endif else return false; return true; } #if MAYA_API_VERSION >= 20180000 bool shaveGlobals::setInternalValue(const MPlug &plug, const MDataHandle &hdl) #else bool shaveGlobals::setInternalValueInContext( const MPlug& plug, const MDataHandle& hdl, MDGContext& ) #endif { if (plug == aNormalRenderMode) { mNormalRenderMode = (shaveConstant::RenderMode)hdl.asShort(); } else if (plug == aNodeVersion) { mNodeVersion = hdl.asInt(); } else if (plug == aHideHair) { bool val = hdl.asBool(); if (val != mHideHair) { mHideHair = val; hideHair(); } } else if (plug == aMaxThreads) { maxThreadsGlob = hdl.asInt(); if (!threadPerProcessorGlob) SHAVEset_max_threads(maxThreadsGlob); } else if (plug == aThreadPerProcessor) { threadPerProcessorGlob = hdl.asBool(); if (threadPerProcessorGlob) SHAVEset_max_threads(-1); else SHAVEset_max_threads(maxThreadsGlob); } #if !DRA_OPTIONAL else if (plug == aUseDRA) { } #endif else return false; return true; } MStatus shaveGlobals::setDependentsDirty( const MPlug& dirty, MPlugArray& affected ) { if(dirty == aDisplayGuides || dirty == aDisplayGuideThick) { MFnDagNode nodeFn; MDagPathArray paths; shaveUtil::getShaveNodes(paths); //it should not trigger ::compute for (unsigned int i = 0; i < paths.length(); i++) { nodeFn.setObject(paths[i].node()); if (nodeFn.typeId() == shaveHairShape::id) { shaveHairShape* shape = (shaveHairShape*)nodeFn.userNode(); shape->dirtyGuides(); MPlug triggerPlug = nodeFn.findPlug("trigger"); float value; triggerPlug.getValue(value); triggerPlug.setValue(value+1.0f); MHWRender::MRenderer::setGeometryDrawDirty(paths[i].node()); } } //M3dView::active3dView().refresh(); } if(dirty == displayDoFallbackAttr) { //bool e; //dirty.getValue(e); //doFallbackGlob = !e; doFallbackGlob = !doFallbackGlob; MGlobal::displayInfo(MString("Shave display fallback: ") + (doFallbackGlob ? "enabled":"disabled")); MFnDagNode nodeFn; MDagPathArray paths; shaveUtil::getShaveNodes(paths); //it should not trigger ::compute for (unsigned int i = 0; i < paths.length(); i++) { nodeFn.setObject(paths[i].node()); if (nodeFn.typeId() == shaveHairShape::id) { shaveHairShape* shape = (shaveHairShape*)nodeFn.userNode(); shape->dirtyDisplay(); shape->dirties.DIRTY_DISPLAY_COUNT = 1; shape->dirties.DIRTY_TEXTURE = 1; //need to update cache as well MPlug triggerPlug = nodeFn.findPlug("trigger"); float value; triggerPlug.getValue(value); triggerPlug.setValue(value+1.0f); // MHWRender::MRenderer::setGeometryDrawDirty(paths[i].node()); } } } if(dirty == aHideHair) { //hideHairGlob = !hideHairGlob; MFnDagNode nodeFn; MDagPathArray paths; shaveUtil::getShaveNodes(paths); //it should not trigger ::compute for (unsigned int i = 0; i < paths.length(); i++) { nodeFn.setObject(paths[i].node()); if (nodeFn.typeId() == shaveHairShape::id) { shaveHairShape* shape = (shaveHairShape*)nodeFn.userNode(); shape->dirtyDisplay(); shape->dirties.DIRTY_DISPLAY_COUNT = 1; shape->dirties.DIRTY_TEXTURE = 1; //need to update cache as well MPlug triggerPlug = nodeFn.findPlug("trigger"); float value; triggerPlug.getValue(value); triggerPlug.setValue(value+1.0f); // MHWRender::MRenderer::setGeometryDrawDirty(paths[i].node()); } } } if(dirty == aDisplaySegmentLimit) { MFnDagNode nodeFn; MDagPathArray paths; shaveUtil::getShaveNodes(paths); //it should not trigger ::compute for (unsigned int i = 0; i < paths.length(); i++) { nodeFn.setObject(paths[i].node()); if (nodeFn.typeId() == shaveHairShape::id) { shaveHairShape* shape = (shaveHairShape*)nodeFn.userNode(); shape->dirtyDisplay(); shape->dirties.DIRTY_DISPLAYSEGS = 1; MPlug triggerPlug = nodeFn.findPlug("trigger"); float value; triggerPlug.getValue(value); triggerPlug.setValue(value+1.0f); // MHWRender::MRenderer::setGeometryDrawDirty(paths[i].node()); } } } if(dirty == aLiveMode || dirty == displayFallbackRatioAttr || dirty == displayHairRatioAttr || dirty == aGlInst || dirty == displayHiarDoXparency) { MFnDagNode nodeFn; MDagPathArray paths; shaveUtil::getShaveNodes(paths); //it should not trigger ::compute for (unsigned int i = 0; i < paths.length(); i++) { nodeFn.setObject(paths[i].node()); if (nodeFn.typeId() == shaveHairShape::id) { shaveHairShape* shape = (shaveHairShape*)nodeFn.userNode(); shape->dirtyDisplay(); shape->dirties.DIRTY_DISPLAY_COUNT = 1; shape->dirties.DIRTY_TEXTURE = 1; //need to update cache as well //MPlug instPlug = nodeFn.findPlug("instancingStatus"); //if(!instPlug.isNull()) { //bool s; //instPlug.getValue(s); //if(s) { MPlug triggerPlug = nodeFn.findPlug("trigger"); float value; triggerPlug.getValue(value); triggerPlug.setValue(value+1.0f); //M3dView::active3dView().refresh(true,true); //MPlug countPlug = nodeFn.findPlug("hairCount"); //int c; //countPlug.getValue(c); //countPlug.setValue(c); } } // MHWRender::MRenderer::setGeometryDrawDirty(paths[i].node()); } } //M3dView::active3dView().refresh(); } return MPxNode::setDependentsDirty(dirty,affected); } //works for legacy void shaveGlobals::hideHair() { MObjectArray hairNodes; unsigned i; shaveUtil::getShaveNodes(hairNodes); for (i = 0; i < hairNodes.length(); i++) { MPlug dspyModePlug(hairNodes[i], shaveHairShape::dspyMode); short displayMode; dspyModePlug.getValue(displayMode); if (mHideHair && (displayMode != shaveHairShape::kHairDisplayNone)) dspyModePlug.setValue(shaveHairShape::kHairDisplayNone); else if (!mHideHair && (displayMode == shaveHairShape::kHairDisplayNone)) { MFnDependencyNode dFn(hairNodes[i]); shaveHairShape* sh = (shaveHairShape*)dFn.userNode(); if(sh->getInstancingStatus()) dspyModePlug.setValue(shaveHairShape::kHairDisplayGeom); else dspyModePlug.setValue(shaveHairShape::kHairDisplayHair); } // Hide the display node as well, otherwise the hair node will // continue to evaluate because the display mesh will keep // requesting mesh updates. // // %%% shaveHairShape should really do this in response to changes // its display mode. MPlugArray conns; MPlug displayNodePlug(hairNodes[i], shaveHairShape::displayNodeAttr); displayNodePlug.connectedTo(conns, true, false); if ((conns.length() > 0) && conns[0].node().hasFn(MFn::kDagNode)) { MPlug displayNodeVisibilityPlug( conns[0].node(), MPxSurfaceShape::visibility ); bool visibility; displayNodeVisibilityPlug.getValue(visibility); if (visibility == mHideHair) { visibility = !visibility; displayNodeVisibilityPlug.setValue(visibility); } } } }