//---------------------------------------------------
    MObject DagHelper::createAnimationCurve ( const MPlug& plug, const char* curveType )
    {
        MStatus rc;
        MFnDependencyNode curveFn;
        curveFn.create ( curveType, &rc );

        if ( rc == MStatus::kSuccess )
        {
            DagHelper::connect ( curveFn.object(), "output", plug );
        }

        return curveFn.object();
    }
MStatus PRTAttrs::addColorParameter(MFnDependencyNode & node, MObject & attr, const MString & name, MString & value ) {
	MStatus             stat;
	MFnNumericAttribute nAttr;

	const wchar_t* s = value.asWChar();

	attr = nAttr.createColor(longName(name), briefName(name), &stat );
	MCHECK(stat);

	double r = 0.0;
	double g = 0.0;
	double b = 0.0;

	if (s[0] == '#' && wcslen(s) >= 7) {
		r = (double)((prtu::fromHex(s[1]) << 4) + prtu::fromHex(s[2])) / 255.0;
		g = (double)((prtu::fromHex(s[3]) << 4) + prtu::fromHex(s[4])) / 255.0;
		b = (double)((prtu::fromHex(s[5]) << 4) + prtu::fromHex(s[6])) / 255.0;

		nAttr.setDefault(r, g, b);
	}

	MCHECK(addParameter(node, attr, nAttr));

	MFnNumericData fnData;
	MObject        rgb = fnData.create(MFnNumericData::k3Double, &stat);
	MCHECK(stat);

	fnData.setData(r, g, b);
	MPlug plug(node.object(), attr);
	MCHECK(plug.setValue(rgb));

	return MS::kSuccess;
}
MStatus PRTAttrs::addBoolParameter(MFnDependencyNode & node, MObject & attr, const MString & name, bool value) {
	MStatus stat;
	MFnNumericAttribute nAttr;
	attr = nAttr.create(longName(name), briefName(name), MFnNumericData::kBoolean, value, &stat);
	if ( stat != MS::kSuccess ) throw stat;

	MCHECK(addParameter(node, attr, nAttr));

	MPlug plug(node.object(), attr);
	MCHECK(plug.setValue(value));

	return MS::kSuccess;
}
MStatus PRTAttrs::addStrParameter(MFnDependencyNode & node, MObject & attr, const MString & name, MString & value ) {
	MStatus           stat;
	MStatus           stat2;
	MFnStringData		  stringData;
	MFnTypedAttribute sAttr;

	attr = sAttr.create(longName(name), briefName(name), MFnData::kString, stringData.create(value, &stat2), &stat );
	MCHECK(stat2);
	MCHECK(stat);
	MCHECK(addParameter(node, attr, sAttr));

	MPlug plug(node.object(), attr);
	MCHECK(plug.setValue(value));

	return MS::kSuccess;
}
MStatus PRTAttrs::addEnumParameter(MFnDependencyNode & node, MObject & attr, const MString & name, short value, PRTEnum * e) {


	MStatus stat;

	attr = e->mAttr.create(longName(name), briefName(name), value, &stat);
	MCHECK(stat);

	MCHECK(e->fill());

	MCHECK(addParameter(node, attr, e->mAttr));

	MPlug plug(node.object(), attr);
	MCHECK(plug.setValue(value));

	return MS::kSuccess;
}
Exemple #6
0
static MObject EntityNodeParent( MDagPath& path )
{
    if( path.hasFn( MFn::kDagNode ) )
    {
        MDagPath parentPath;
        MFnDependencyNode nodeFn;

        while( path.pop( 1 ) != MS::kInvalidParameter )
        {        
            nodeFn.setObject( path.node() );
            if( nodeFn.typeId() == EntityInstanceNode::s_TypeID )    
            {
                return nodeFn.object();
            }
        }
    }

    return MObject::kNullObj;
}
MStatus PRTAttrs::addFloatParameter(MFnDependencyNode & node, MObject & attr, const MString & name, double value, double min, double max) {
	MStatus stat;
	MFnNumericAttribute nAttr;
	attr = nAttr.create(longName(name), briefName(name), MFnNumericData::kDouble, value, &stat );
	if ( stat != MS::kSuccess ) throw stat;

	if(!isnan(min)) {
		MCHECK(nAttr.setMin(min));
	}

	if(!isnan(max)) {
		MCHECK(nAttr.setMax( max ));
	}

	MCHECK(addParameter(node, attr, nAttr));

	MPlug plug(node.object(), attr);
	MCHECK(plug.setValue(value));

	return MS::kSuccess;
}
MStatus PRTAttrs::updateRuleFiles(MFnDependencyNode & node, MString & rulePkg) {
	PRTNode* prtNode = (PRTNode*)node.userNode();
	MStatus  stat;

	std::string utf8Path(rulePkg.asUTF8());
	std::vector<char> percentEncodedPath(2*utf8Path.size()+1);
	size_t len = percentEncodedPath.size();
	prt::StringUtils::percentEncode(utf8Path.c_str(), &percentEncodedPath[0], &len);
	if(len > percentEncodedPath.size()+1){
		percentEncodedPath.resize(len);
		prt::StringUtils::percentEncode(utf8Path.c_str(), &percentEncodedPath[0], &len);
	}

	std::string uri(FILE_PREFIX);
	uri.append(&percentEncodedPath[0]);

	prtNode->mLRulePkg = uri;

	if(prtNode->mCreatedInteractively) {
		int count = (int)node.attributeCount(&stat);
		MCHECK(stat);

		MObjectArray attrs;

		for(int i = 0; i < count; i++) {
			MObject attr = node.attribute(i, &stat);
			if(stat != MS::kSuccess) continue;
			attrs.append(attr);
		}

		for(unsigned int i = 0; i < attrs.length(); i++) {
			MPlug   plug(node.object(), attrs[i]);
			MString name = plug.partialName();

			if(prtNode->mBriefName2prtAttr.count(name.asWChar()))
				node.removeAttribute(attrs[i]);
		}
		prtNode->destroyEnums();
	} else {
		node.removeAttribute(node.attribute(NAME_GENERATE, &stat));
		MCHECK(stat);
	}

	prtNode->mRuleFile.clear();
	prtNode->mStartRule.clear();

	MString      unpackDir       = MGlobal::executeCommandStringResult("workspace -q -fullName");
	unpackDir += "/assets";
	prt::Status resolveMapStatus = prt::STATUS_UNSPECIFIED_ERROR;


	std::wstring utf16URI;
	utf16URI.resize(uri.size()+1);
	len = utf16URI.size();
	if(prt::StringUtils::toUTF16FromUTF8(uri.c_str(), &utf16URI[0], &len)) {
		utf16URI.resize(len);
		prt::StringUtils::toUTF16FromUTF8(uri.c_str(), &utf16URI[0], &len);
	}

	prtNode->mResolveMap = prt::createResolveMap(utf16URI.c_str(), unpackDir.asWChar(), &resolveMapStatus);
	if(resolveMapStatus == prt::STATUS_OK) {
		size_t nKeys;
		const wchar_t * const* keys   = prtNode->mResolveMap->getKeys(&nKeys);
		std::wstring           sCGB(L".cgb");
		for(size_t k = 0; k < nKeys; k++) {
			std::wstring key = std::wstring(keys[k]);
			if(std::equal(sCGB.rbegin(), sCGB.rend(), key.rbegin())) {
				prtNode->mRuleFile = key;
				break;
			}
		}
	} else {
		prtNode->mResolveMap = 0;
	}

	if(prtNode->mRuleFile.length() > 0)
		updateStartRules(node);

	return MS::kSuccess;
}
Corona::SharedPtr<Corona::Abstract::Map> getOslTexMap(MString& attributeName, MFnDependencyNode& depFn, ShadingNetwork& sn)
{
	MStatus status;
	OSL::OSLShadingNetworkRenderer *oslRenderer;
	MayaTo::MayaToWorld::WorldRenderType rType = MayaTo::getWorldPtr()->getRenderType();
	if ((rType == MayaTo::MayaToWorld::WorldRenderType::SWATCHRENDER))
	{
		oslRenderer = (OSL::OSLShadingNetworkRenderer *)MayaTo::getObjPtr("oslSwatchRenderer");
	}
	else{
		oslRenderer = (OSL::OSLShadingNetworkRenderer *)MayaTo::getObjPtr("oslRenderer");
	}

	size_t numNodes = sn.shaderList.size();
	MString OSLInterfaceName = depFn.name() + "_" + attributeName + "_OSLInterface";
	MString shaderGroupName = depFn.name() + "_" + attributeName + "_OSLShadingGroup";
	OSL::ShaderGroupRef shaderGroup = oslRenderer->shadingsys->ShaderGroupBegin(shaderGroupName.asChar());

	MObject thisMObject = depFn.object();
	MString outPlugName;
	MString connectedObjectName = getObjectName(getOtherSideSourceNode(attributeName, thisMObject, true, outPlugName));

	Logging::debug(MString("getOslTexMap: ") + connectedObjectName + "." + outPlugName + " is connected with " + depFn.name() + "." + attributeName);
	MPlug shaderPlug = depFn.findPlug(attributeName);

	MAYATO_OSL::createOSLProjectionNodes(shaderPlug);

	for (int shadingNodeId = 0; shadingNodeId < numNodes; shadingNodeId++)
	{
		ShadingNode snode = sn.shaderList[shadingNodeId];
		Logging::debug(MString("ShadingNode Id: ") + shadingNodeId + " ShadingNode name: " + snode.fullName);
		MAYATO_OSL::createOSLHelperNodes(sn.shaderList[shadingNodeId]);
		MAYATO_OSL::createOSLShadingNode(sn.shaderList[shadingNodeId]);
		MAYATO_OSL::connectProjectionNodes(sn.shaderList[shadingNodeId].mobject);

		if (snode.fullName == connectedObjectName.asChar())
		{
			MAYATO_OSL::createOSLHelperNodes(sn.shaderList[sn.shaderList.size() - 1]);
			Logging::debug(MString("connected node found: ") + snode.fullName + " search output attr.");

			for (size_t outId = 0; outId < snode.outputAttributes.size(); outId++)
			{
				ShaderAttribute& sa = snode.outputAttributes[outId];
				if (MString(sa.name.c_str()) == outPlugName)
				{
					Logging::debug(MString("connected out attr found: ") + sa.name.c_str() + " ");

					MString destParam;
					MString sourceParam = outPlugName;
					MString sourceNode = connectedObjectName;
					if ((sa.type == "color") || (sa.type == "vector"))
					{
						// lets see if we have a color helper node
						MString helperNodeName = MAYATO_OSL::createPlugHelperNodeName(attributeName.asChar(), thisMObject, false);
						Logging::debug(MString("Interface connection - color/vector attribute ") + sa.name.c_str() + " search for helper node " + helperNodeName);
						if (MAYATO_OSL::doesOSLNodeAlreadyExist(helperNodeName))
						{
							Logging::debug(MString("Found helper node name."));
							sourceParam = "outputValue";
							sourceNode = helperNodeName;
						}
						destParam = "inVector";
					}
					if (sa.type == "float")
					{
						destParam = "inFloat";
					}
					if (sa.type == "int")
					{
						destParam = "inInt";
					}
					if (sa.type == "bool")
					{
						destParam = "inBool";
					}

					if (sourceParam == "output")
						sourceParam = "outOutput";

					// if we have a color/vector input, try to find a multiplier attribute
					MString multiplierName = attributeName + "Multiplier";
					MPlug multiplierAttribute = depFn.findPlug(multiplierName, true, &status);
					if (status)
					{
						Logging::debug(MString("Found multiplier attribute: ") + multiplierName);
						float multiplier = multiplierAttribute.asFloat();
						float offset = 0.0f;
						if ((attributeName == "refractionIndex") || (attributeName == "reflectionIor"))
						{
							offset = -1.0f;
						}
						oslRenderer->shadingsys->Parameter("multiplier", OSL::TypeDesc::TypeFloat, &multiplier);
						oslRenderer->shadingsys->Parameter("offset", OSL::TypeDesc::TypeFloat, &offset);
					}
					Logging::debug(MString("creating OSLInterface shader ") + OSLInterfaceName);
					bool success = oslRenderer->shadingsys->Shader("surface", "OSLInterface", OSLInterfaceName.asChar());
					Logging::debug(MString("connecting ") + sourceNode + "." + sourceParam + " -> " + OSLInterfaceName + "." + destParam);
					success = oslRenderer->shadingsys->ConnectShaders(sourceNode.asChar(), sourceParam.asChar(), OSLInterfaceName.asChar(), destParam.asChar());
					break;
				}
			}
			break;
		}
	}
	if (!oslRenderer->shadingsys->ShaderGroupEnd())
	{
		Logging::debug("Problem finishing shader group");
	}
	std::string serialized;
	oslRenderer->shadingsys->getattribute(shaderGroup.get(), "pickle", serialized);
	Logging::debug(MString("Serialized: ") + serialized.c_str());

	Corona::SharedPtr<Corona::Abstract::Map> oslMapp = new OSLMap;
	OSLMap *oslMap = (OSLMap *)oslMapp.getReference();

	oslMap->oslRenderer = oslRenderer;
	oslMap->shaderGroup = shaderGroup;
	
	if (depFn.object().hasFn(MFn::kLight))
		oslMap->isLightMap = true;

	if (attributeName == "normalCamera")
	{
		oslMap->bumpType = OSLMap::NONE;
		// we only support direct bumpmap connections
		MPlug ncPlug = depFn.findPlug("normalCamera");
		if (ncPlug.isConnected())
		{
			MPlugArray pa;
			ncPlug.connectedTo(pa, true, false);
			if (pa.length() > 0)
			{
				for (uint pId = 0; pId < pa.length(); pId++)
				{
					if (pa[pId].node().hasFn(MFn::kBump) || pa[pId].node().hasFn(MFn::kBump3d))
					{
						MFnDependencyNode bumpFn(pa[pId].node());
						MPlug interpPlug = bumpFn.findPlug("bumpInterp");
						if (interpPlug.asInt() == 0)
							oslMap->bumpType = OSLMap::BUMP;
						if (interpPlug.asInt() == 1)
							oslMap->bumpType = OSLMap::NORMALTANGENT;
						if (interpPlug.asInt() == 2)
							oslMap->bumpType = OSLMap::NORMALOBJECT;
						if (pa[pId].node().hasFn(MFn::kBump3d))
							oslMap->bumpType = OSLMap::BUMP3D;
					}
				}
			}
		}
	}
	return oslMapp;
}
void CScriptedShapeTranslator::RunScripts(AtNode *atNode, unsigned int step, bool update)
{
   std::map<std::string, CScriptedTranslator>::iterator translatorIt;
   MFnDependencyNode fnNode(GetMayaObject());
   
   translatorIt = gTranslators.find(fnNode.typeName().asChar());
   if (translatorIt == gTranslators.end())
   {
      AiMsgError("[mtoa.scriptedTranslators] No command to export node \"%s\" of type %s.", fnNode.name().asChar(), fnNode.typeName().asChar());
      return;
   }
   
   MString exportCmd = translatorIt->second.exportCmd;
   MString cleanupCmd = translatorIt->second.cleanupCmd;
   
   MFnDagNode node(m_dagPath.node());
   
   bool isMasterDag = false;
   bool transformBlur = IsMotionBlurEnabled(MTOA_MBLUR_OBJECT) && IsLocalMotionBlurEnabled();
   bool deformBlur = IsMotionBlurEnabled(MTOA_MBLUR_DEFORM) && IsLocalMotionBlurEnabled();
   
   char buffer[64];
   
   MString command = exportCmd;
   command += "(";
   
   sprintf(buffer, "%f", GetExportFrame());
   command += buffer;
   command += ", ";
   
   sprintf(buffer, "%d", step);
   command += buffer;
   command += ", ";
   
   // current sample frame
   sprintf(buffer, "%f", GetSampleFrame(m_session, step));
   command += buffer;
   command += ", ";
   
   // List of arnold attributes the custom shape export command has overriden
   MStringArray attrs;
   
   if (!m_masterNode)
   {
      command += "(\"" + m_dagPath.partialPathName() + "\", \"";
      command += AiNodeGetName(atNode);
      command += "\"), None)";
      isMasterDag = true;
   }
   else
   {
      command += "(\"" + m_dagPath.partialPathName() + "\", \"";
      command += AiNodeGetName(atNode);
      command += "\"), (\"" + GetMasterInstance().partialPathName() + "\", \"";
      command += AiNodeGetName(m_masterNode);
      command += "\"))";
   }
   
   MStatus status = MGlobal::executePythonCommand(command, attrs);
   if (!status)
   {
      AiMsgError("[mtoa.scriptedTranslators] Failed to export node \"%s\".", node.name().asChar());
      return;
   }
   
   // Build set of attributes already processed
   std::set<std::string> attrsSet;
   for (unsigned int i=0; i<attrs.length(); ++i)
   {
      attrsSet.insert(attrs[i].asChar());
   }
   std::set<std::string>::iterator attrsEnd = attrsSet.end();
   
   // Should be getting displacement shader from master instance only
   //   as arnold do not support displacement shader overrides for ginstance
   MFnDependencyNode masterShadingEngine;
   MFnDependencyNode shadingEngine;
   float dispPadding = -AI_BIG;
   float dispHeight = 1.0f;
   float dispZeroValue = 0.0f;
   bool dispAutobump = false;
   bool outputDispPadding = false;
   bool outputDispHeight = false;
   bool outputDispZeroValue = false;
   bool outputDispAutobump = false;
   
   const AtNodeEntry *anodeEntry = AiNodeGetNodeEntry(atNode);
   
   GetShapeInstanceShader(m_dagPath, shadingEngine);
   if (!IsMasterInstance())
   {
      GetShapeInstanceShader(GetMasterInstance(), masterShadingEngine);
   }
   else
   {
      masterShadingEngine.setObject(shadingEngine.object());
   }
   
   AtMatrix matrix;
   MMatrix mmatrix = m_dagPath.inclusiveMatrix();
   ConvertMatrix(matrix, mmatrix);
   
   // Set transformation matrix
   if (attrsSet.find("matrix") == attrsEnd)
   {
      if (HasParameter(anodeEntry, "matrix"))
      {
         if (transformBlur)
         {
            if (step == 0)
            {
               AtArray* matrices = AiArrayAllocate(1, GetNumMotionSteps(), AI_TYPE_MATRIX);
               AiArraySetMtx(matrices, step, matrix);
               AiNodeSetArray(atNode, "matrix", matrices);
            }
            else
            {
               AtArray* matrices = AiNodeGetArray(atNode, "matrix");
               AiArraySetMtx(matrices, step, matrix);
            }
         }
         else
         {
            AiNodeSetMatrix(atNode, "matrix", matrix);
         }
      }
   }
   
   // Set bounding box
   if (attrsSet.find("min") == attrsEnd && attrsSet.find("max") == attrsEnd)
   {
      // Now check if min and max parameters are valid parameter names on arnold node
      if (HasParameter(anodeEntry, "min") != 0 && HasParameter(anodeEntry, "max") != 0)
      {
         if (step == 0)
         {
            MBoundingBox bbox = node.boundingBox();
            
            MPoint bmin = bbox.min();
            MPoint bmax = bbox.max();
            
            AiNodeSetPnt(atNode, "min", static_cast<float>(bmin.x), static_cast<float>(bmin.y), static_cast<float>(bmin.z));
            AiNodeSetPnt(atNode, "max", static_cast<float>(bmax.x), static_cast<float>(bmax.y), static_cast<float>(bmax.z));
         }
         else
         {
            if (transformBlur || deformBlur)
            {
               AtPoint cmin = AiNodeGetPnt(atNode, "min");
               AtPoint cmax = AiNodeGetPnt(atNode, "max");
               
               MBoundingBox bbox = node.boundingBox();
               
               MPoint bmin = bbox.min();
               MPoint bmax = bbox.max();
               
               if (bmin.x < cmin.x)
                  cmin.x = static_cast<float>(bmin.x);
               if (bmin.y < cmin.y)
                  cmin.y = static_cast<float>(bmin.y);
               if (bmin.z < cmin.z)
                  cmin.z = static_cast<float>(bmin.z);
               if (bmax.x > cmax.x)
                  cmax.x = static_cast<float>(bmax.x);
               if (bmax.y > cmax.y)
                  cmax.y = static_cast<float>(bmax.y);
               if (bmax.z > cmax.z)
                  cmax.z = static_cast<float>(bmax.z);
               
               AiNodeSetPnt(atNode, "min", cmin.x, cmin.y, cmin.z);
               AiNodeSetPnt(atNode, "max", cmax.x, cmax.y, cmax.z);
            }
         }
      }
   }
   
   if (step == 0)
   {
      // Set common attributes
      MPlug plug;
      
      if (AiNodeIs(atNode, "procedural"))
      {
         // Note: it is up to the procedural to properly forward (or not) those parameters to the node
         //       it creates
         
         if (attrsSet.find("subdiv_type") == attrsEnd)
         {
            plug = FindMayaPlug("subdiv_type");
            if (plug.isNull())
            {
               plug = FindMayaPlug("aiSubdivType");
            }
            if (!plug.isNull() && HasParameter(anodeEntry, "subdiv_type", atNode, "constant INT"))
            {
               AiNodeSetInt(atNode, "subdiv_type", plug.asInt());
            }
         }
         
         if (attrsSet.find("subdiv_iterations") == attrsEnd)
         {
            plug = FindMayaPlug("subdiv_iterations");
            if (plug.isNull())
            {
               plug = FindMayaPlug("aiSubdivIterations");
            }
            if (!plug.isNull() && HasParameter(anodeEntry, "subdiv_iterations", atNode, "constant BYTE"))
            {
               AiNodeSetByte(atNode, "subdiv_iterations", plug.asInt());
            }
         }
         
         if (attrsSet.find("subdiv_adaptive_metric") == attrsEnd)
         {
            plug = FindMayaPlug("subdiv_adaptive_metric");
            if (plug.isNull())
            {
               plug = FindMayaPlug("aiSubdivAdaptiveMetric");
            }
            if (!plug.isNull() && HasParameter(anodeEntry, "subdiv_adaptive_metric", atNode, "constant INT"))
            {
               AiNodeSetInt(atNode, "subdiv_adaptive_metric", plug.asInt());
            }
         }
         
         if (attrsSet.find("subdiv_pixel_error") == attrsEnd)
         {
            plug = FindMayaPlug("subdiv_pixel_error");
            if (plug.isNull())
            {
               plug = FindMayaPlug("aiSubdivPixelError");
            }
            if (!plug.isNull() && HasParameter(anodeEntry, "subdiv_pixel_error", atNode, "constant FLOAT"))
            {
               AiNodeSetFlt(atNode, "subdiv_pixel_error", plug.asFloat());
            }
         }
         
         if (attrsSet.find("subdiv_dicing_camera") == attrsEnd)
         {
            plug = FindMayaPlug("subdiv_dicing_camera");
            if (plug.isNull())
            {
               plug = FindMayaPlug("aiSubdivDicingCamera");
            }
            if (!plug.isNull() && HasParameter(anodeEntry, "subdiv_dicing_camera", atNode, "constant NODE"))
            {
               AtNode *cameraNode = NULL;
               
               MPlugArray plugs;
               plug.connectedTo(plugs, true, false);
               
               if (plugs.length() == 1)
               {
                  MFnDagNode camDag(plugs[0].node());
                  MDagPath camPath;
                  
                  if (camDag.getPath(camPath) == MS::kSuccess)
                  {
                     cameraNode = ExportDagPath(camPath);
                  }
               }
               
               AiNodeSetPtr(atNode, "subdiv_dicing_camera", cameraNode);
            }
         }
         
         if (attrsSet.find("subdiv_uv_smoothing") == attrsEnd)
         {
            plug = FindMayaPlug("subdiv_uv_smoothing");
            if (plug.isNull())
            {
               plug = FindMayaPlug("aiSubdivUvSmoothing");
            }
            if (!plug.isNull() && HasParameter(anodeEntry, "subdiv_uv_smoothing", atNode, "constant INT"))
            {
               AiNodeSetInt(atNode, "subdiv_uv_smoothing", plug.asInt());
            }
         }
         
         if (attrsSet.find("subdiv_smooth_derivs") == attrsEnd)
         {
            plug = FindMayaPlug("aiSubdivSmoothDerivs");
            if (!plug.isNull() && HasParameter(anodeEntry, "subdiv_smooth_derivs", atNode, "constant BOOL"))
            {
               AiNodeSetBool(atNode, "subdiv_smooth_derivs", plug.asBool());
            }
         }
         
         if (attrsSet.find("smoothing") == attrsEnd)
         {
            // Use maya shape built-in attribute
            plug = FindMayaPlug("smoothShading");
            if (!plug.isNull() && HasParameter(anodeEntry, "smoothing", atNode, "constant BOOL"))
            {
               AiNodeSetBool(atNode, "smoothing", plug.asBool());
            }
         }
         
         if (attrsSet.find("disp_height") == attrsEnd)
         {
            plug = FindMayaPlug("aiDispHeight");
            if (!plug.isNull())
            {
               outputDispHeight = true;
               dispHeight = plug.asFloat();
            }
         }
         
         if (attrsSet.find("disp_zero_value") == attrsEnd)
         {
            plug = FindMayaPlug("aiDispZeroValue");
            if (!plug.isNull())
            {
               outputDispZeroValue = true;
               dispZeroValue = plug.asFloat();
            }
         }
         
         if (attrsSet.find("disp_autobump") == attrsEnd)
         {
            plug = FindMayaPlug("aiDispAutobump");
            if (!plug.isNull())
            {
               outputDispAutobump = true;
               dispAutobump = plug.asBool();
            }
         }
         
         if (attrsSet.find("disp_padding") == attrsEnd)
         {
            plug = FindMayaPlug("aiDispPadding");
            if (!plug.isNull())
            {
               outputDispPadding = true;
               dispPadding = MAX(dispPadding, plug.asFloat());
            }
         }
         
         // Set diplacement shader
         if (attrsSet.find("disp_map") == attrsEnd)
         {
            if (masterShadingEngine.object() != MObject::kNullObj)
            {
               MPlugArray shaderConns;
               
               MPlug shaderPlug = masterShadingEngine.findPlug("displacementShader");
               
               shaderPlug.connectedTo(shaderConns, true, false);
               
               if (shaderConns.length() > 0)
               {
                  MFnDependencyNode dispNode(shaderConns[0].node());
                  
                  plug = dispNode.findPlug("aiDisplacementPadding");
                  if (!plug.isNull())
                  {
                     outputDispPadding = true;
                     dispPadding = MAX(dispPadding, plug.asFloat());
                  }
                  
                  plug = dispNode.findPlug("aiDisplacementAutoBump");
                  if (!plug.isNull())
                  {
                     outputDispAutobump = true;
                     dispAutobump = dispAutobump || plug.asBool();
                  }
                  
                  if (HasParameter(anodeEntry, "disp_map", atNode, "constant ARRAY NODE"))
                  {
                     AtNode *dispImage = ExportNode(shaderConns[0]);
                     AiNodeSetArray(atNode, "disp_map", AiArrayConvert(1, 1, AI_TYPE_NODE, &dispImage));
                  }
               }
            }
         }
         
         if (outputDispHeight && HasParameter(anodeEntry, "disp_height", atNode, "constant FLOAT"))
         {
            AiNodeSetFlt(atNode, "disp_height", dispHeight);
         }
         if (outputDispZeroValue && HasParameter(anodeEntry, "disp_zero_value", atNode, "constant FLOAT"))
         {
            AiNodeSetFlt(atNode, "disp_zero_value", dispZeroValue);
         }
         if (outputDispPadding && HasParameter(anodeEntry, "disp_padding", atNode, "constant FLOAT"))
         {
            AiNodeSetFlt(atNode, "disp_padding", dispPadding);
         }
         if (outputDispAutobump && HasParameter(anodeEntry, "disp_autobump", atNode, "constant BOOL"))
         {
            AiNodeSetBool(atNode, "disp_autobump", dispAutobump);
         }
         
         // Old point based SSS parameter
         if (attrsSet.find("sss_sample_distribution") == attrsEnd)
         {
            plug = FindMayaPlug("sss_sample_distribution");
            if (plug.isNull())
            {
               plug = FindMayaPlug("aiSssSampleDistribution");
            }
            if (!plug.isNull() && HasParameter(anodeEntry, "sss_sample_distribution", atNode, "constant INT"))
            {
               AiNodeSetInt(atNode, "sss_sample_distribution", plug.asInt());
            }
         }
         
         // Old point based SSS parameter
         if (attrsSet.find("sss_sample_spacing") == attrsEnd)
         {
            plug = FindMayaPlug("sss_sample_spacing");
            if (plug.isNull())
            {
               plug = FindMayaPlug("aiSssSampleSpacing");
            }
            if (!plug.isNull() && HasParameter(anodeEntry, "sss_sample_spacing", atNode, "constant FLOAT"))
            {
               AiNodeSetFlt(atNode, "sss_sample_spacing", plug.asFloat());
            }
         }
         
         if (attrsSet.find("min_pixel_width") == attrsEnd)
         {
            plug = FindMayaPlug("aiMinPixelWidth");
            if (!plug.isNull() && HasParameter(anodeEntry, "min_pixel_width", atNode, "constant FLOAT"))
            {
               AiNodeSetFlt(atNode, "min_pixel_width", plug.asFloat());
            }
         }
         
         if (attrsSet.find("mode") == attrsEnd)
         {
            plug = FindMayaPlug("aiMode");
            if (!plug.isNull() && HasParameter(anodeEntry, "mode", atNode, "constant INT"))
            {
               AiNodeSetInt(atNode, "mode", plug.asShort());
            }
         }
         
         if (attrsSet.find("basis") == attrsEnd)
         {
            plug = FindMayaPlug("aiBasis");
            if (!plug.isNull() && HasParameter(anodeEntry, "basis", atNode, "constant INT"))
            {
               AiNodeSetInt(atNode, "basis", plug.asShort());
            }
         }
      }
      
      if (AiNodeIs(atNode, "ginstance"))
      {
         if (attrsSet.find("node") == attrsEnd)
         {
            AiNodeSetPtr(atNode, "node", m_masterNode);
         }
         
         if (attrsSet.find("inherit_xform") == attrsEnd)
         {
            AiNodeSetBool(atNode, "inherit_xform", false);
         }
      }
      else
      {
         // box or procedural
         if (attrsSet.find("step_size") == attrsEnd)
         {
            plug = FindMayaPlug("step_size");
            if (plug.isNull())
            {
               plug = FindMayaPlug("aiStepSize");
            }
            if (!plug.isNull() && HasParameter(anodeEntry, "step_size", atNode, "constant FLOAT"))
            {
               AiNodeSetFlt(atNode, "step_size", plug.asFloat());
            }
         }
      }
      
      if (attrsSet.find("sidedness") == attrsEnd)
      {
         // Use maya shape built-in attribute
         plug = FindMayaPlug("doubleSided");
         if (!plug.isNull() && HasParameter(anodeEntry, "sidedness", atNode, "constant BYTE"))
         {
            AiNodeSetByte(atNode, "sidedness", plug.asBool() ? AI_RAY_ALL : 0);
            
            // Only set invert_normals if doubleSided attribute could be found
            if (!plug.asBool() && attrsSet.find("invert_normals") == attrsEnd)
            {
               // Use maya shape built-in attribute
               plug = FindMayaPlug("opposite");
               if (!plug.isNull() && HasParameter(anodeEntry, "invert_normals", atNode, "constant BOOL"))
               {
                  AiNodeSetBool(atNode, "invert_normals", plug.asBool());
               }
            }
         }
      }
      
      if (attrsSet.find("receive_shadows") == attrsEnd)
      {
         // Use maya shape built-in attribute
         plug = FindMayaPlug("receiveShadows");
         if (!plug.isNull() && HasParameter(anodeEntry, "receive_shadows", atNode, "constant BOOL"))
         {
            AiNodeSetBool(atNode, "receive_shadows", plug.asBool());
         }
      }
      
      if (attrsSet.find("self_shadows") == attrsEnd)
      {
         plug = FindMayaPlug("self_shadows");
         if (plug.isNull())
         {
            plug = FindMayaPlug("aiSelfShadows");
         }
         if (!plug.isNull() && HasParameter(anodeEntry, "self_shadows", atNode, "constant BOOL"))
         {
            AiNodeSetBool(atNode, "self_shadows", plug.asBool());
         }
      }
      
      if (attrsSet.find("opaque") == attrsEnd)
      {
         plug = FindMayaPlug("opaque");
         if (plug.isNull())
         {
            plug = FindMayaPlug("aiOpaque");
         }
         if (!plug.isNull() && HasParameter(anodeEntry, "opaque", atNode, "constant BOOL"))
         {
            AiNodeSetBool(atNode, "opaque", plug.asBool());
         }
      }
      
      if (attrsSet.find("visibility") == attrsEnd)
      {
         if (HasParameter(anodeEntry, "visibility", atNode, "constant BYTE"))
         {
            int visibility = AI_RAY_ALL;
            
            // Use maya shape built-in attribute
            plug = FindMayaPlug("castsShadows");
            if (!plug.isNull() && !plug.asBool())
            {
               visibility &= ~AI_RAY_SHADOW;
            }
            
            // Use maya shape built-in attribute
            plug = FindMayaPlug("primaryVisibility");
            if (!plug.isNull() && !plug.asBool())
            {
               visibility &= ~AI_RAY_CAMERA;
            }
            
            // Use maya shape built-in attribute
            plug = FindMayaPlug("visibleInReflections");
            if (!plug.isNull() && !plug.asBool())
            {
               visibility &= ~AI_RAY_REFLECTED;
            }
            
            // Use maya shape built-in attribute
            plug = FindMayaPlug("visibleInRefractions");
            if (!plug.isNull() && !plug.asBool())
            {
               visibility &= ~AI_RAY_REFRACTED;
            }
            
            plug = FindMayaPlug("diffuse_visibility");
            if (plug.isNull())
            {
               plug = FindMayaPlug("aiVisibleInDiffuse");
            }
            if (!plug.isNull() && !plug.asBool())
            {
               visibility &= ~AI_RAY_DIFFUSE;
            }
            
            plug = FindMayaPlug("glossy_visibility");
            if (plug.isNull())
            {
               plug = FindMayaPlug("aiVisibleInGlossy");
            }
            if (!plug.isNull() && !plug.asBool())
            {
               visibility &= ~AI_RAY_GLOSSY;
            }
            
            AiNodeSetByte(atNode, "visibility", visibility & 0xFF);
         }
      }
      
      if (attrsSet.find("sss_setname") == attrsEnd)
      {
         plug = FindMayaPlug("aiSssSetname");
         if (!plug.isNull() && plug.asString().length() > 0)
         {
            if (HasParameter(anodeEntry, "sss_setname", atNode, "constant STRING"))
            {
               AiNodeSetStr(atNode, "sss_setname", plug.asString().asChar());
            }
         }
      }
      
      // Set surface shader
      if (HasParameter(anodeEntry, "shader", atNode, "constant NODE"))
      {
         if (attrsSet.find("shader") == attrsEnd)
         {
            if (shadingEngine.object() != MObject::kNullObj)
            {
               AtNode *shader = ExportNode(shadingEngine.findPlug("message"));
               if (shader != NULL)
               {
                  const AtNodeEntry *entry = AiNodeGetNodeEntry(shader);
                  
                  if (AiNodeEntryGetType(entry) != AI_NODE_SHADER)
                  {
                     MGlobal::displayWarning("[mtoaScriptedTranslators] Node generated from \"" + shadingEngine.name() +
                                             "\" of type " + shadingEngine.typeName() + " for shader is not a shader but a " +
                                             MString(AiNodeEntryGetTypeName(entry)));
                  }
                  else
                  {
                     AiNodeSetPtr(atNode, "shader", shader);
                     
                     if (AiNodeLookUpUserParameter(atNode, "mtoa_shading_groups") == 0)
                     {
                        AiNodeDeclare(atNode, "mtoa_shading_groups", "constant ARRAY NODE");
                        AiNodeSetArray(atNode, "mtoa_shading_groups", AiArrayConvert(1, 1, AI_TYPE_NODE, &shader));
                     }
                  }
               }
            }
         }
      }
   }
   
   ExportLightLinking(atNode);
   
   MPlug plug = FindMayaPlug("aiTraceSets");
   if (!plug.isNull())
   {
      ExportTraceSets(atNode, plug);
   }
   
   // Call cleanup command on last export step
   
   if (!IsMotionBlurEnabled() || !IsLocalMotionBlurEnabled() || int(step) >= (int(GetNumMotionSteps()) - 1))
   {
      if (HasParameter(anodeEntry, "disp_padding", atNode))
      {
         float padding = AiNodeGetFlt(atNode, "disp_padding");
         
         AtPoint cmin = AiNodeGetPnt(atNode, "min");
         AtPoint cmax = AiNodeGetPnt(atNode, "max");
         
         cmin.x -= padding;
         cmin.y -= padding;
         cmin.z -= padding;
         cmax.x += padding;
         cmax.y += padding;
         cmax.z += padding;
         
         AiNodeSetPnt(atNode, "min", cmin.x, cmin.y, cmin.z);
         AiNodeSetPnt(atNode, "max", cmax.x, cmax.y, cmax.z);
      }
      
      if (cleanupCmd != "")
      {
         command = cleanupCmd += "((\"" + m_dagPath.partialPathName() + "\", \"";
         command += AiNodeGetName(atNode);
         command += "\"), ";
         
         if (!m_masterNode)
         {
            command += "None)";
         }
         else
         {
            command += "(\"" + GetMasterInstance().partialPathName() + "\", \"";
            command += AiNodeGetName(m_masterNode);
            command += "\"))";
         }
         
         status = MGlobal::executePythonCommand(command);
         
         if (!status)
         {
            AiMsgError("[mtoa.scriptedTranslators] Failed to cleanup node \"%s\".", node.name().asChar());
         }
      }
   }
}
NifTextureConnector::NifTextureConnector(MFnDependencyNode texture_placement, int uv_set) {
	this->texturePlacement.setObject(texture_placement.object());
	this->uvSet = uv_set;
}