void HwShaderExporter::setTexture (
        const PBBitmap * bitmap, 
        COLLADASW::Sampler& sampler
        )
    {
        if ( !bitmap )
        {
            //:TODO: retrieve default values from fx file
            return;
        }

        // Set the texture format.
        //:TODO: read from BitmapInfo::Type ()
        sampler.setFormat ( EffectTextureExporter::FORMAT );

        // Get the necessary exporters.
        EffectExporter* effectExporter = mDocumentExporter->getEffectExporter ();
        EffectTextureExporter* textureExporter = effectExporter->getTextureExporter();
        
        // The file name to connect to.
#ifdef UNICODE
		String fileName = bitmap->bi.Name() ? COLLADASW::URI::nativePathToUri( COLLADABU::StringUtils::wideString2utf8String(bitmap->bi.Name()) ) : "";
#else
        String fileName = bitmap->bi.Name() ? COLLADASW::URI::nativePathToUri( bitmap->bi.Name() ) : "";
#endif

        // Export, if we have a file name.
        if ( !fileName.empty () )
        {
            // Get the image path
            COLLADASW::URI shaderFxFileUri = mEffectProfile->getIncludeURI();

            // Take the filename for the unique image name
            COLLADASW::URI sourceFileUri ( shaderFxFileUri, fileName );
            if ( sourceFileUri.getScheme ().empty () )
                sourceFileUri.setScheme ( COLLADASW::URI::SCHEME_FILE );
            String maxImageId = /*DocumentExporter::mayaNameToColladaName*/ ( sourceFileUri.getPathFileBase().c_str () );

            // Get the image id of the maya image 
            String colladaImageId = textureExporter->findColladaImageId ( maxImageId );

            if ( colladaImageId.empty () )
            {
                colladaImageId = textureExporter->getImageIdList ().addId ( maxImageId );
                textureExporter->getMaxIdColladaImageId () [maxImageId] = colladaImageId;
            }

            // Export the image
            COLLADASW::Image* colladaImage = textureExporter->exportImage ( maxImageId, colladaImageId, sourceFileUri );

            // Get the image id of the exported collada image
            colladaImageId = colladaImage->getImageId();

            // Set the image reference
            sampler.setImageId ( colladaImageId );
        }
    }
	void ShaderFXShaderExporter::exportSamplerAndSurfaceInner(const MString & filename)
	{
		EffectExporter & effectExporter = *mDocumentExporter.getEffectExporter();
		EffectTextureExporter & textureExporter = *effectExporter.getTextureExporter();

		// Take the filename for the unique image name
		URI fileURI(URI::nativePathToUri(filename.asChar()));
		if (fileURI.getScheme().empty())
			fileURI.setScheme(COLLADASW::URI::SCHEME_FILE);

		String mayaImageId = DocumentExporter::mayaNameToColladaName(fileURI.getPathFileBase().c_str());

		String colladaImageId = effectExporter.findColladaImageId(mayaImageId);
		if (colladaImageId.empty())
		{
			// Generate a COLLADA id for the new image object
			colladaImageId = DocumentExporter::mayaNameToColladaName(fileURI.getPathFileBase().c_str());

			// Make the id unique and store it in a map for refernences.
			colladaImageId = textureExporter.getImageIdList().addId(colladaImageId);
			textureExporter.getMayaIdColladaImageId()[mayaImageId] = colladaImageId;
		}

		// Export the image
		COLLADASW::Image* colladaImage = textureExporter.exportImage(mayaImageId, colladaImageId, fileURI);

		// Get the image id of the exported collada image
		colladaImageId = colladaImage->getImageId();

		String samplerSid = colladaImageId + COLLADASW::Sampler::SAMPLER_SID_SUFFIX;
		String surfaceSid = colladaImageId + COLLADASW::Sampler::SURFACE_SID_SUFFIX;

		// Create the collada sampler object
		// TODO handle other sampler types
		COLLADASW::Sampler sampler(COLLADASW::Sampler::SAMPLER_TYPE_2D, samplerSid, surfaceSid);

		// TODO get wrap mode in ShaderFX graph
		//sampler.setWrapS(COLLADASW::Sampler::WRAP_MODE_WRAP);
		//sampler.setWrapT(COLLADASW::Sampler::WRAP_MODE_WRAP);
		//sampler.setWrapP(COLLADASW::Sampler::WRAP_MODE_WRAP);

		// No filtering option in ShaderFX. Default to linear.
		//sampler.setMinFilter(COLLADASW::Sampler::SAMPLER_FILTER_LINEAR);
		//sampler.setMagFilter(COLLADASW::Sampler::SAMPLER_FILTER_LINEAR);
		//sampler.setMipFilter(COLLADASW::Sampler::SAMPLER_FILTER_LINEAR);

		// Set the image reference
		sampler.setImageId(colladaImageId);

		sampler.setFormat(EffectTextureExporter::FORMAT);

		// Add the parameter.
		sampler.addInNewParam(&mStreamWriter);
	}
    //---------------------------------------------------------------
    String EffectTextureExporter::exportImage ( const MObject &texture )
    {
        // Retrieve the texture filename
        MFnDependencyNode textureNode ( texture );
        MString mayaName = textureNode.name();
        MPlug filenamePlug = textureNode.findPlug ( ATTR_FILE_TEXTURE_NAME );

        // Get the maya image id.
        String mayaImageId = DocumentExporter::mayaNameToColladaName ( textureNode.name() );

        // Generate a COLLADA id for the new light object
        String colladaImageId;

        // Check if there is an extra attribute "colladaId" and use this as export id.
        MString attributeValue;
        DagHelper::getPlugValue ( texture, COLLADA_ID_ATTRIBUTE_NAME, attributeValue );
        if ( attributeValue != EMPTY_CSTRING )
        {
            // Generate a valid collada name, if necessary.
            colladaImageId = mDocumentExporter->mayaNameToColladaName ( attributeValue, false );
        }
        else
        {
            // Generate a COLLADA id for the new light object
            colladaImageId = DocumentExporter::mayaNameToColladaName ( textureNode.name() );
        }
        // Make the id unique and store it in a map for refernences.
        colladaImageId = mImageIdList.addId ( colladaImageId );
        mMayaIdColladaImageId [mayaImageId] = colladaImageId;

        // Get the maya filename with the path to the file.
        MString mayaFileName;
        filenamePlug.getValue ( mayaFileName );
        if ( mayaFileName.length () == 0 ) return NULL;
        String sourceFile = mayaFileName.asChar ();
        COLLADASW::URI sourceFileUri ( COLLADASW::URI::nativePathToUri ( sourceFile ) );
        if ( sourceFileUri.getScheme ().empty () )
            sourceFileUri.setScheme ( COLLADASW::URI::SCHEME_FILE );

        COLLADASW::Image* colladaImage = exportImage ( mayaImageId, colladaImageId, sourceFileUri );
        if ( colladaImage == NULL ) return NULL;

        // Export the node type, because PSD textures don't behave the same as File textures.
        String nodeType = texture.hasFn ( MFn::kPsdFileTexture ) ? MAYA_TEXTURE_PSDTEXTURE : MAYA_TEXTURE_FILETEXTURE;
        colladaImage->addExtraTechniqueParameter ( PROFILE_MAYA, MAYA_TEXTURE_NODETYPE, nodeType );

        // Export whether this image is in fact an image sequence
        MPlug imgSeqPlug = textureNode.findPlug ( ATTR_IMAGE_SEQUENCE );
        bool isImgSeq = false;
        imgSeqPlug.getValue ( isImgSeq );
        colladaImage->addExtraTechniqueParameter ( PROFILE_MAYA, MAYA_TEXTURE_IMAGE_SEQUENCE, isImgSeq );

        return colladaImage->getImageId();
    }
    // -------------------------------
    COLLADASW::Image* EffectTextureExporter::exportImage ( 
        const String& mayaImageId, 
        const String& colladaImageId, 
        const COLLADASW::URI& sourceUri )
    {
        // Get the file name and the URI
        COLLADASW::URI fullFileNameURI;
        bool sourceFileExist = getTextureFileInfos ( sourceUri, fullFileNameURI );
        String fullFileName = fullFileNameURI.toNativePath ();

        // Have we seen this texture node before?
        ImageMap::iterator exportedImagesIter = mExportedImageMap.find ( fullFileName );
        if ( exportedImagesIter != mExportedImageMap.end() )
        {
            COLLADASW::Image* colladaImage = ( *exportedImagesIter ).second;
            return colladaImage;
        }

        // Check, if we should copy the texture to the destination folder.
        if ( ExportOptions::copyTextures() )
        {
            // Get the target file from source file.
            COLLADASW::URI targetUri = createTargetURI ( sourceUri );

            if ( !exists ( sourceUri.toNativePath() ) )
            {
                String message = "The source texture file doesn't exist! Filename = " + sourceUri.toNativePath();
                std::cerr << message << std::endl;
            }
            else
            {
                // Copy the texture, if it isn't already there...
                if ( !exists( targetUri.toNativePath () ) )
                {
                    try 
                    {
                        // Create the target directory, if necessary. 
                        // Note: some systems (window$) requires the string to be 
                        // enclosed in quotes when a space is present.
                        COLLADASW::URI targetPathUri ( targetUri.getPathDir() );
                        create_directory ( targetPathUri.toNativePath() );

                        // Throws: basic_filesystem_error<Path> if
                        // from_fp.empty() || to_fp.empty() ||!exists(from_fp) || !is_regular(from_fp) || exists(to_fp)
                        copy_file ( path ( sourceUri.toNativePath() ), path ( targetUri.toNativePath() ) );
                    }
                    catch ( std::exception ex )
                    {
                        String message = "Could not successful create directory and copy file: " + sourceUri.toNativePath();
                        MGlobal::displayError( message.c_str() );
                        std::cerr << "[ERROR] Could not copy file " << sourceUri.toNativePath() << std::endl;
                    }
                }
            }
        }

        // Create a new image structure
        COLLADASW::Image* colladaImage = new COLLADASW::Image ( fullFileNameURI, colladaImageId, mayaImageId );

        // Export the original maya name.
        colladaImage->addExtraTechniqueParameter ( PROFILE_MAYA, PARAMETER_MAYA_ID, mayaImageId );

        // Add this texture to our list of exported images
        mExportedImageMap[ fullFileName ] = colladaImage;

        return colladaImage;
    }
    //---------------------------------------
    void MaterialExporter::setSetParamTexture (
        const cgfxAttrDef* attribute, 
        MObject texture, 
        COLLADASW::Sampler::SamplerType samplerType, 
        COLLADASW::ValueType::ColladaType samplerValueType )
    {
        // Get a pointer to the current stream writer.
        COLLADASW::StreamWriter* streamWriter = mDocumentExporter->getStreamWriter();

        // Get the image id
        MFnDependencyNode textureNode ( texture );
        String plugName = textureNode.name().asChar(); // file1

        // Get the file texture name
        MPlug filenamePlug = textureNode.findPlug ( ATTR_FILE_TEXTURE_NAME );
        MString mayaFileName;
        filenamePlug.getValue ( mayaFileName );
        if ( mayaFileName.length() == 0 ) return;
        String fileName = mayaFileName.asChar ();
        
        // Get the image path
        COLLADASW::URI shaderFxFileUri = getShaderFxFileUri ();

        // Take the filename for the unique image name 
        COLLADASW::URI sourceFileUri ( shaderFxFileUri, fileName );
        if ( sourceFileUri.getScheme ().empty () )
            sourceFileUri.setScheme ( COLLADASW::URI::SCHEME_FILE );
        String mayaImageId = DocumentExporter::mayaNameToColladaName ( sourceFileUri.getPathFileBase().c_str () );

        // Get the image id of the maya image 
        EffectExporter* effectExporter = mDocumentExporter->getEffectExporter ();
        String colladaImageId = effectExporter->findColladaImageId ( mayaImageId );
        if ( colladaImageId.empty () )
        {
            // Check if there is an extra attribute "colladaId" and use this as export id.
            MString attributeValue;
            DagHelper::getPlugValue ( texture, COLLADA_ID_ATTRIBUTE_NAME, attributeValue );
            if ( attributeValue != EMPTY_CSTRING )
            {
                // Generate a valid collada name, if necessary.
                colladaImageId = mDocumentExporter->mayaNameToColladaName ( attributeValue, false );
            }
            else
            {
                // Generate a COLLADA id for the new light object
                colladaImageId = DocumentExporter::mayaNameToColladaName ( textureNode.name() );
            }
            // Make the id unique and store it in a map for refernences.
            EffectTextureExporter* textureExporter = effectExporter->getTextureExporter ();
            colladaImageId = textureExporter->getImageIdList ().addId ( colladaImageId );
            textureExporter->getMayaIdColladaImageId () [mayaImageId] = colladaImageId;
        }

        // Export the image
        EffectTextureExporter* textureExporter = mDocumentExporter->getEffectExporter()->getTextureExporter();
        COLLADASW::Image* colladaImage = textureExporter->exportImage ( mayaImageId, colladaImageId, sourceFileUri );
        mayaImageId = colladaImage->getImageId();

        // Create the sampler and surface sid
        String samplerSid = mayaImageId + COLLADASW::Sampler::SAMPLER_SID_SUFFIX;
        String surfaceSid = mayaImageId + COLLADASW::Sampler::SURFACE_SID_SUFFIX;

        // Avoid export of dublicate sampler params
        if ( mSamplers.find ( samplerSid ) != mSamplers.end () ) return;
        mSamplers.insert ( samplerSid );

        // Create the sampler and add the sampler <setparam>
        COLLADASW::Sampler sampler ( samplerType, samplerSid, surfaceSid );
        sampler.setFormat ( EffectTextureExporter::FORMAT );
        sampler.setImageId ( colladaImage->getImageId() );
        sampler.addInSetParam ( streamWriter );
    }