//------------------------------
    void LightImporter::importLight ( const COLLADAFW::Light* light )
    {
        // Check if the light is already imported.
        const COLLADAFW::UniqueId& lightId = light->getUniqueId ();
        if ( findMayaLightNode ( lightId ) != 0 ) return;

        // Get the transform nodes, which work with this light instance.
        VisualSceneImporter* visualSceneImporter = getDocumentImporter ()->getVisualSceneImporter ();
        const UniqueIdVec* transformNodes = visualSceneImporter->findLightTransformIds ( lightId );
        if ( transformNodes == 0 )
        {
            std::cerr << "No transform node which implements this light!" << std::endl;
            return;
        }

        UniqueIdVec::const_iterator nodesIter = transformNodes->begin ();
        while ( nodesIter != transformNodes->end () )
        {
            // Get the maya node of the current transform node.
            const COLLADAFW::UniqueId& transformNodeId = *nodesIter;
            MayaNodesList* mayaNodesList = visualSceneImporter->findMayaTransformNodes ( transformNodeId );
            if ( mayaNodesList == 0 ) 
            {
                std::cerr << "Cant find transform node!" << std::endl;
                return;
            }
            MayaNode* mayaTransformNode = (*mayaNodesList) [0];
            String transformNodeName = mayaTransformNode->getName ();

            // Get the path to the parent transform node.
            String transformNodePath = mayaTransformNode->getNodePath ();

            // The first reference is a direct one, the others are instances.
            if ( nodesIter == transformNodes->begin() )
            {
                // Create the current mesh node.
                createLight ( light, mayaTransformNode );
            }
            else
            {
                // Get the path to the node.
                MayaNode* mayaLightNode = findMayaLightNode ( lightId );
                String lightNodePath = mayaLightNode->getNodePath ();

                // parent -shape -noConnections -relative -addObject "|pCube1|pCubeShape1" "pCube2";
                FILE* file = getDocumentImporter ()->getFile ();
                MayaDM::parentShape ( file, lightNodePath, transformNodePath, false, true, true, true );
            }

            ++nodesIter;
        }
    }
//------------------------------
void LightImporter::createAndAddAmbientLight( const COLLADAFW::Light* light )
{
    if ( light->getLightType() == COLLADAFW::Light::AMBIENT_LIGHT )
    {
        getDocumentImporter()->addAmbientColor(light->getColor());
    }
}
    //------------------------------
    void LightImporter::initialiseDefaultLightObjects ()
    {
        // Get a reference to the current maya ascii file.
        FILE* file = getDocumentImporter ()->getFile ();

        // Create the default light linker
        mDefaultLightLinker.setFile ( file );
        mDefaultLightLinker.setName ( DEFAULT_LIGHT_LINKER_NAME );

        // Create a object for the default light list.
        mDefaultLightList.setFile ( file );
        mDefaultLightList.setName ( ":" + DEFAULT_LIGHT_LIST_NAME );
        
        // Create a object for the default light set.
        mDefaultLightSet.setFile ( file );
        mDefaultLightSet.setName ( ":" + DEFAULT_LIGHT_SET_NAME );

    }
    // --------------------------
    void LightImporter::connectLightObjects ()
    {
        // The maya ascii file.
        FILE* file = getDocumentImporter ()->getFile ();

        size_t lightIndex = 0;
        size_t lightSetIndex = 0;
        UniqueIdMayaNodeMap::iterator it = mMayaLightNodesMap.begin ();
        while ( it != mMayaLightNodesMap.end () )
        {
            const COLLADAFW::UniqueId& lightId = it->first;
            MayaNode* mayaNode = it->second;

            MayaDM::DependNode* dependNode = findMayaLight ( lightId );
            MayaDM::Light* lightNode = ( MayaDM::Light* ) dependNode;
            dependNode->setName ( mayaNode->getNodePath () );

            // Connect the light data of the lights (just real ones, no instances), with the light list.
            //connectAttr "|spotLight1|spotLightShape1.lightData" ":lightList1.lights" -nextAvailable;
            //connectAttr "spotLightShape2.lightData" ":lightList1.lights" -nextAvailable;
            connectAttr ( file, lightNode->getLightData (), mDefaultLightList.getLights ( lightIndex ) );
            ++lightIndex;

            // Get the transform nodes, which work with this light instance.
            VisualSceneImporter* visualSceneImporter = getDocumentImporter ()->getVisualSceneImporter ();
            const UniqueIdVec* transformNodes = visualSceneImporter->findLightTransformIds ( lightId );
            if ( transformNodes == 0 )
            {
                std::cerr << "No transform node which implements this light!" << std::endl;
                return;
            }

            size_t nodeIndex = 0;
            UniqueIdVec::const_iterator nodesIter = transformNodes->begin ();
            while ( nodesIter != transformNodes->end () )
            {
                // Get the maya transform nodes and read the path.
                const COLLADAFW::UniqueId& transformNodeId = *nodesIter;
                MayaNodesList* transformNodes = visualSceneImporter->findMayaTransformNodes ( transformNodeId );
                if ( transformNodes->size () == 0 )
                {
                    std::cerr << "The referenced transform node doesn't exist!" << std::endl;
                    return;
                }
                MayaNode* mayaTransformNode = (*transformNodes) [0];
                String transformNodeName = mayaTransformNode->getName ();
                String transformNodePath = mayaTransformNode->getNodePath ();
                MayaDM::Transform transformNode ( file, transformNodePath, EMPTY_STRING, false, false );

                // Connect the light transforms instance object groups with the default light set.
                //connectAttr "spotLight1.instObjGroups" ":defaultLightSet.dagSetMembers" -nextAvailable;
                //connectAttr "|spotLight2.instObjGroups" ":defaultLightSet.dagSetMembers" -nextAvailable;
                //connectAttr "spotLight3.instObjGroups" ":defaultLightSet.dagSetMembers" -nextAvailable;
                connectNextAttr ( file, transformNode.getInstObjGroups (), mDefaultLightSet.getDagSetMembers () );
                //connectAttr ( file, transformNode.getInstObjGroups (0), mDefaultLightSet.getDagSetMembers (lightSetIndex) );
                ++lightSetIndex;

                ++nodesIter;
            }
            
            ++it;
        }
    }
    // --------------------------
    void LightImporter::connectLightLinkers ()
    {
        // The maya ascii file.
        FILE* file = getDocumentImporter ()->getFile ();

        size_t lightLinkerLinkIndex = 0;

        // Get the default light set.
        MayaDM::ObjectSet defaultLightSet ( file, DEFAULT_LIGHT_SET_NAME, EMPTY_STRING, false, false );

        // Connect the existing shader engines with the first light linker link's object.
        MaterialImporter* materialImporter = getDocumentImporter ()->getMaterialImporter ();
        const MaterialImporter::ShadingDataMap& shadingDataMap = materialImporter->getShadingEnginesMap ();
        MaterialImporter::ShadingDataMap::const_iterator it = shadingDataMap.begin ();
        while ( it != shadingDataMap.end () )
        {
            MaterialImporter::ShadingData* shadingData = it->second;
            const MayaDM::ShadingEngine& shadingEngine = shadingData->getShadingEngine ();

            // Connect the the default light set message with the next light linker link's light
            // connectAttr ":defaultLightSet.message" "lightLinker1.link[0].light";
            connectAttr ( file, defaultLightSet.getMessage (), mDefaultLightLinker.getLight ( lightLinkerLinkIndex ) );

            // Connect the current shading engine's message with the next light linker link's object.
            // connectAttr "lambert2SG.message" "lightLinker1.link[0].object";
            connectAttr ( file, shadingEngine.getMessage (), mDefaultLightLinker.getObject ( lightLinkerLinkIndex ) );

            // Connect the the default light set message with the next light linker shadow link's shadow light
            // connectAttr ":defaultLightSet.message" "lightLinker1.shadowLink[0].shadowLight";
            connectAttr ( file, defaultLightSet.getMessage (), mDefaultLightLinker.getShadowLight ( lightLinkerLinkIndex ) );

            // Connect the current shading engine's message with the next light linker shadow link's shadow object.
            // connectAttr "lambert2SG.message" "lightLinker1.shadowLink[0].shadowObject";
            connectAttr ( file, shadingEngine.getMessage (), mDefaultLightLinker.getShadowObject ( lightLinkerLinkIndex ) );

            // Increment the light linker index
            ++lightLinkerLinkIndex;

            ++it;
        }

        // Create the dummy object of the initial shading group.
        MayaDM::ShadingEngine initialShadingEngine ( file, ":" + MaterialImporter::INITIAL_SHADING_ENGINE_NAME, EMPTY_STRING, false, false );

        // Connect the default light set message with the next light linker link's light
        // connectAttr ":defaultLightSet.message" "lightLinker1.link[1].light";
        connectAttr ( file, defaultLightSet.getMessage (), mDefaultLightLinker.getLight ( lightLinkerLinkIndex ) );
        // Connect the initial shading group message with the next light linker link's object
        // connectAttr ":initialShadingGroup.message" "lightLinker1.link[1].object";
        connectAttr ( file, initialShadingEngine.getMessage (), mDefaultLightLinker.getObject ( lightLinkerLinkIndex ) );

        // Connect the default light set message with the light linker shadow link's shadow light
        // connectAttr ":defaultLightSet.message" "lightLinker1.shadowLink[1].shadowLight";
        connectAttr ( file, defaultLightSet.getMessage (), mDefaultLightLinker.getShadowLight ( lightLinkerLinkIndex ) );
        // Connect the initial shading group message with the next light linker shadow link's shadow object
        // connectAttr ":initialShadingGroup.message" "lightLinker1.shadowLink[1].shadowObject";
        connectAttr ( file, initialShadingEngine.getMessage (), mDefaultLightLinker.getShadowObject ( lightLinkerLinkIndex ) );

        // Connect the light linker the initial light list link Nodes
        // connectAttr "lightLinker1.message" ":lightList1.linkNodes" -nextAvailable;
        connectAttr ( file, mDefaultLightLinker.getMessage (), mDefaultLightList.getLinkNodes (0) );

    }
    // --------------------------------------------
    void LightImporter::createLight ( 
        const COLLADAFW::Light* light,  
        MayaNode* mayaTransformNode )
    {
        // Check if the camera is already imported.
        const COLLADAFW::UniqueId& lightId = light->getUniqueId ();

        // Make the maya name unique and manage it in all necessary lists.
        String lightName = light->getName ();
        if ( lightName.empty () ) lightName = LIGHT_NAME;
        lightName = DocumentImporter::frameworkNameToMayaName ( lightName );
        const ExtraDataCallbackHandler& callbackHandler = getDocumentImporter ()->getMayaIdCallbackHandler ();
        String originalMayaId = getOriginalMayaId ( callbackHandler, lightId, COLLADASaxFWL15::HASH_ELEMENT_LIGHT );
        if ( !originalMayaId.empty () ) lightName = originalMayaId;
        lightName = generateUniqueDagNodeName ( lightName, mayaTransformNode );

        // Create a maya node object of the current node and push it into the map.
        MayaNode* mayaLightNode = new MayaNode ( lightId, lightName, mayaTransformNode );
        mMayaLightNodesMap [ lightId ] = mayaLightNode;

        FILE* file = getDocumentImporter ()->getFile ();

        MayaDM::Light* mayaLight = 0;
        COLLADAFW::Light::LightType lightType = light->getLightType ();
        switch ( lightType )
        {
        case COLLADAFW::Light::AMBIENT_LIGHT:
            {
                mayaLight = new MayaDM::AmbientLight ( file, lightName, mayaTransformNode->getNodePath () );
            }
            break;
        case COLLADAFW::Light::DIRECTIONAL_LIGHT:
            {
                mayaLight = new MayaDM::DirectionalLight ( file, lightName, mayaTransformNode->getNodePath () );
            }
            break;
        case COLLADAFW::Light::POINT_LIGHT:
            {
                mayaLight = new MayaDM::PointLight ( file, lightName, mayaTransformNode->getNodePath () );
                setPointLightAttributes ( light, mayaLight );
            }
            break;
        case COLLADAFW::Light::SPOT_LIGHT:
            {
                mayaLight = new MayaDM::SpotLight ( file, lightName, mayaTransformNode->getNodePath () );
                setSpotLightAttributes ( light, mayaLight );
            }
            break;
        default:
            std::cerr << "Unknown light type!" << std::endl;
            return;
        }

        // Add the original id attribute.
        String colladaId = light->getOriginalId ();
        if ( !colladaId.empty () )
        {
            MayaDM::addAttr ( file, COLLADA_ID_ATTRIBUTE_NAME, ATTRIBUTE_DATA_TYPE, ATTRIBUTE_TYPE_STRING );
            MayaDM::setAttr ( file, COLLADA_ID_ATTRIBUTE_NAME, ATTRIBUTE_TYPE, ATTRIBUTE_TYPE_STRING, colladaId );
        }
//         // TODO Add the attributes for all the extra tags.
//         setExtraData ( light->getExtraDataArray () );

        // Set the standard light color.
        COLLADAFW::Color color = light->getColor ();
        mayaLight->setColor ( MayaDM::float3 ( (float)color.getRed (), (float)color.getGreen (), (float)color.getBlue () ) );
        
        // Store the light in a map.
        appendLight ( lightId, mayaLight );
    }
	//------------------------------
	StdMat2* MaterialCreator::createStandardMaterial( const COLLADAFW::EffectCommon& effectCommon, const String& name, const MaterialCreator::MaterialIdentifier& materialIdentifier )
	{
		StdMat2* material = NewDefaultStdMat();


		COLLADAFW::EffectCommon::ShaderType shaderType = effectCommon.getShaderType();
		switch ( shaderType )
		{
		case COLLADAFW::EffectCommon::SHADER_CONSTANT: 
			material->SetFaceted(true); // BUG393: Max actually does not support a constant shader!
		case COLLADAFW::EffectCommon::SHADER_BLINN: 
			material->SwitchShader(Class_ID(StandardMaterial::STD2_BLINN_SHADER_CLASS_ID, 0)); 
			break;
		case COLLADAFW::EffectCommon::SHADER_LAMBERT:
		case COLLADAFW::EffectCommon::SHADER_PHONG:
		case COLLADAFW::EffectCommon::SHADER_UNKNOWN:
		default: 
			material->SwitchShader(Class_ID(StandardMaterial::STD2_PHONG_CLASS_ID, 0)); 
			break;
		}


		// Retrieve the shader parameter blocks
		Shader* materialShader = material->GetShader();
		IParamBlock2* shaderParameters = (IParamBlock2*) materialShader->GetReference(0);
		IParamBlock2* extendedParameters = (IParamBlock2*) material->GetReference(StandardMaterial::EXTENDED_PB_REF);

		// Common material parameters
		material->SetName(name.c_str());
		const COLLADAFW::ColorOrTexture& diffuse = effectCommon.getDiffuse();

		if ( diffuse.isColor() )
			material->SetDiffuse( toMaxColor(diffuse), 0);

		const COLLADAFW::ColorOrTexture& emission = effectCommon.getEmission();
		if ( emission.isColor() )
		{
			material->SetSelfIllumColorOn(TRUE);
			material->SetSelfIllumColor( toMaxColor(emission), 0);
		}
		else
		{
			material->SetSelfIllumColorOn(FALSE);
			material->SetSelfIllum( 0, 0 );
		}

		float maxOpacity = 1;
		const COLLADAFW::ColorOrTexture& opacity = effectCommon.getOpacity();
		if ( opacity.isColor() )
		{
			const COLLADAFW::Color& opacityColor = opacity.getColor(); 
			float averageTransparent = (float)(opacityColor.getRed() + opacityColor.getGreen() + opacityColor.getBlue())/3; 
			maxOpacity = averageTransparent;
		}

		if ( getDocumentImporter()->getInvertTransparency() )
		{
			maxOpacity = 1 - maxOpacity;
		}

		// Max seems to like to have opacity 0 for opacity textures
		if ( opacity.isTexture() )
		{
			material->SetOpacity( 0, 0);
		}
		else
		{
			material->SetOpacity( maxOpacity, 0);
		}

		if (shaderType != COLLADAFW::EffectCommon::SHADER_CONSTANT && shaderType != COLLADAFW::EffectCommon::SHADER_UNKNOWN)
		{
			// Unlock the ambient and diffuse colors
			materialShader->SetLockAD(FALSE);
			materialShader->SetLockADTex(FALSE);
			material->LockAmbDiffTex(FALSE);
			material->SyncADTexLock(FALSE);

			// Lambert/Phong material parameters
			const COLLADAFW::ColorOrTexture& ambient = effectCommon.getAmbient();
			if ( ambient.isColor() )
				material->SetAmbient( toMaxColor(ambient), 0);
		}
		else
		{
			// Approximate constant shader, specular is the same color
			if ( diffuse.isColor() )
				material->SetSpecular( toMaxColor(diffuse), 0 );
		}

		const COLLADAFW::ColorOrTexture& specular = effectCommon.getSpecular();
		const COLLADAFW::FloatOrParam& shininessFloatOrParam = effectCommon.getShininess();
		float shininess = 1;
		if ( shininessFloatOrParam.getType() == COLLADAFW::FloatOrParam::FLOAT )
		{
			shininess = shininessFloatOrParam.getFloatValue();
		}
		if ( shaderType == COLLADAFW::EffectCommon::SHADER_PHONG || shaderType == COLLADAFW::EffectCommon::SHADER_BLINN)
		{
			// Phong material parameters
			if ( specular.isColor() )
				material->SetSpecular( toMaxColor(specular), 0 );

			material->SetShininess(ConversionFunctors::fromPercent(shininess), 0);
			material->SetShinStr(ConversionFunctors::fromPercent(shininess), 0);
		}

		//create and assign textures
		createAndAssignTexture( material, effectCommon, &COLLADAFW::EffectCommon::getAmbient, ID_AM, materialIdentifier.ambientMapChannel);
		createAndAssignTexture( material, effectCommon, &COLLADAFW::EffectCommon::getDiffuse, ID_DI, materialIdentifier.diffuseMapChannel);
		createAndAssignTexture( material, effectCommon, &COLLADAFW::EffectCommon::getSpecular, ID_SP, materialIdentifier.specularMapChannel);
		createAndAssignTexture( material, effectCommon, &COLLADAFW::EffectCommon::getEmission, ID_SI, materialIdentifier.emissionMapChannel);
		createAndAssignTexture( material, effectCommon, &COLLADAFW::EffectCommon::getOpacity, ID_OP, materialIdentifier.opacityMapChannel);

		return material;
	}